Azure Bot Framework App with SmartThings Integration
Overview
I have been working on integrating my SmartThings app with an Azure Bot Framework App so I can use Skype, Webchat, or FB Messenger to control the lights in my apartment. Azure bot framework provides the architecture needed to easily create a chat bot that can support a number of different channels such as the ones listed above as well as numerous others. Note at the moment of this post (4/9/17) there is a difference between Azure Bot Service which runs on Azure Function Apps and the Azure bot framework (which is what I used) which would be deployed as an Azure web app or API app. Azure Bot Services use the Azure bot framework, but it is running as a function app do the overall design of the bot will be different and it is still in Preview (beta) as well. This is why I chose to use the Bot Framework deployed to a web app.
You may ask why I choose to integrate my SmartThings with an chat bot when the SmartThings app works perfectly fine. The first reason is because I needed a project to integrate with the Bot Framework to get some familiarity with it. The second reason is I only have the app on my phone. Without logging into my account online I have no other way to control my lights. With this integration I can can control my lights on my PC, phone, or anything that has access to Skype, FB, or the webchat. My end goal at some point is to have a fully functional home automation system that is customized.
Getting Started
- Deploy a Visual Studio Bot Application Template. If you are not seeing this in Visual Studio you need to make sure your Azure SDK and App Services Tooling are up to date. A quick Google search will provide a link for the version of VS you are using. The tutorial linked above will give a general overview of how to create, deploy, and debug the bot. In the template you will see a MessagesControllers.cs which is where the main functionality of the bot lives.
- Creating the API calls to SmartThings API: Following the guide to making API calls from Microsoft, I was able to make the calls to my SmartThings custom app restful API. In my initial testing I created a console app with the general functionality of turning on and off my lights to make sure I had the basics working before integrating it with the Azure bot framework. Authentication to the SmartThings apps requires a bearer token. Instead of having the user log in every time I hard coded my access token that I generated through Postman in the applications app settings. I plan in the future to allow the user to authenticate to a specific app in case the token expires or the user wants to use a different application. The access token can be passed to the client using the following line of code:
client.DefaultRequestHeaders.Add(“Authorization”, “Bearer ” + accessToken); - HTTP Client: The first obstacle I had to overcome was how to properly the HTTP client. Per Microsoft’s documentation (discussed in this blog and this stackoverflow post) you should only use one static instance of the HTTP client, otherwise you can run into issues with resource exhaustion.
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Especially in server applications, creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
I ran into an issue where I was trying to create the client object in the main Post activity and add the headers. Since each message received from a chat will create a new instance of this post method a new client/headers were being created. I was getting errors about the client already existing and the headers existing. To quickly workaround this I declared a variable at the top of my Messages Controller that incremented once the client was initially created. There maybe a better way to resolve this but I didn’t want to focus to much.
if (j == 0)
{
string accessToken = ConfigurationManager.AppSettings[“accessToken”];
client.BaseAddress = new Uri($”https://graph-na02-useast1.api.smartthings.com:443/api/smartapps/installations/”+ ConfigurationManager.AppSettings[“SmartThingsSubscription”] +”/switches”);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
client.DefaultRequestHeaders.Add(“Authorization”, “Bearer ” + accessToken);
j++;
} - Remote Debugging: I found that remote debugging was my best friend in this project while troubleshooting locally as well as debugging the application once deployed to Azure. Whether it was small syntax issues or strange behavior with the authentication process of the bot app, without remote debugging a lot of the issues I ran into would have taken a lot longer to resolve.
- Making a scalable application: The last step I worked on was making my app scalable and not relying on hard-coded inputs for the API calls or responses back to the user. With the current setup, I can add any device that can be turned on, off, or some version of dimmed/level change such as more lights, thermostat, or smart outlets. I will need to make minor adjustments to the response wording but those will be quick changes.
Conclusion
Feel free to comment if you have any recommend changes or functionality requests.
Code Repositories:
Azure Bot: https://github.com/jcbrooks92/ChatBotService-HomeAutomation
SmartThings App: https://github.com/jcbrooks92/SmartThingsCode-HomeAuto