AIM
To control home appliances from anywhere in the world
HARDWARE & SOFTWARE REQUIREMENTS
- Mini PC- We can use the Arduino board / Rasphberry pi / Minix neo z64 mini PC
Photo by Nick Hubbard / CC BY
Image Credits: Minix.com.hk - Insteon-compatible home automation devices
- Insteon 2413U or 2413S module
- Insteon 2635-222 On/Off module
Image Credits: tech69.net
- Speakers
- Azure Cloud hosting subscription
- Internet connection
- Visual Studio 2010
INTRODUCTION
In this article we’ll have look at controlling home appliances remotely over HTTP using a small API toolset we’ll create using ASP.NET MVC. On top of that we’ll push the current device status to the client in real time with SignalR(windows service hosted)
We will Control following home appliances through windows service:
1. FAN - on/off, Speed adjust
2. Lights - on/off
3. Air Conditioner - on/off, Temperature Control
4. Speakers – on/off, Play/Pause/Stop song
THE PLAN
We will create a windows service for controlling Insteon devices, then we will build a SignalR web service which will interact with the windows service and finally we will build a mobile application to send commands to the web service so that we can control the devices from anywhere on the web
Part I Building windows service for controlling Insteon devices
Part II Building remote control service for sending commands to windows service from ASP.NET MVC and SignalR
Part III Building mobile web application for interacting with web api service
IMPLEMENTATION
To start up with we will implement just controlling of lights on & off
Part I Building windows service for controlling Insteon devices
1. Create new .NET 4.0 console application project in visual studio & add reference of TopShelf to it using NuGet package manager(With topshelf we can build easily debuggable windows service)
2. Add reference to the FluenDwelling API dll file, Programmatical interaction with Insteon hardware devices is easy because some great souls on the Internet have managed to create the API structure. I came across a great project called as FluentDwelling:
http://soapboxautomation.com/products/fluentdwelling/
3. We will host the signalR client in the windows service,
In the NuGet package manager console type following command:
Install-Package Microsoft.AspNet.SignalR.Client -Version 1.2.2
4. Add new class called as "InsteonService.cs" to the windows service project
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using Microsoft.AspNet.SignalR.Client;
using SoapBox.FluentDwelling;
using Topshelf;
namespace IoT.WindowsService
{
public class InsteonService : ServiceControl
{
private static string ServiceUri;
private static Connection connection;
private static Plm plm = new Plm("COM4");
public bool Start(HostControl hostControl)
{
ServiceUri = ConfigurationManager.AppSettings["ServiceUri"];
connection = new Connection(ServiceUri, "name=Client");
connection.Received += connection_Received;
connection.StateChanged += connection_StateChanged;
Console.WriteLine("Connecting...");
connection.Start().Wait();
string inputMsg;
while (!string.IsNullOrEmpty(inputMsg = Console.ReadLine()))
{
connection.Send(inputMsg).Wait();
}
connection.Stop();
return true;
}
static void connection_StateChanged(StateChange state)
{
if (state.NewState == ConnectionState.Connected)
{
Console.WriteLine("Connected.");
}
}
static void connection_Received(string data)
{
string[] command = data.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (command.Length > 0)
if (command[0].Equals("Server", StringComparison.InvariantCultureIgnoreCase))
{
string commandName = command[1].ToLower();
if (command.Length > 2)
{
string deviceid = command[2];
switch (commandName)
{
case "turnoff":
{
plm.Network.X10
.House("A")
.Unit(2)
.Command(X10Command.Off);
}
break;
case "turnon":
{
plm.Network.X10
.House("A")
.Unit(2)
.Command(X10Command.On);
}
break;
}
}
else
{
switch (commandName)
{
case "getlist":
{
var database = plm.GetAllLinkDatabase();
string devices = "";
if (!plm.Error)
{
foreach (var record in database.Records)
{
devices += record.DeviceId.ToString();
}
}
else
{
devices += "Error";
}
connection.Send(devices).Wait();
}
break;
}
}
}
}
public bool Stop(HostControl hostControl)
{
if (connection.State == ConnectionState.Connected)
connection.Stop();
return true;
}
}
}
5. In "Program.cs" write following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Topshelf;
using Topshelf.HostConfigurators;
using Topshelf.ServiceConfigurators;
namespace IoT.WindowsService
{
class Program
{
static void Main(string[] args)
{
var host = HostFactory.New(ConfigureHost);
host.Run();
}
private static void ConfigureHost(HostConfigurator x)
{
x.Service<insteonservice>(ConfigureService);
x.SetDisplayName("Insteon Service");
x.SetDescription("Insteon Controller Service");
x.SetInstanceName("Insteon");
x.SetServiceName("Insteon");
x.StartAutomatically();
x.RunAsPrompt();
}
private static void ConfigureService(ServiceConfigurator<insteonservice> sc)
{
sc.ConstructUsing(() => new InsteonService());
sc.WhenStarted((s, hostControl) => s.Start(hostControl));
sc.WhenStopped((s, hostControl) => s.Stop(hostControl));
}
}
}
</insteonservice></insteonservice>
6. Finally in the "App.config" file in the "AppSettings" section we need to add following lines of code
<add key="ServiceUri" value="http://insteoniot.azurewebsites.net/echo"/>
Part II Building remote control service for sending commands to windows service from ASP.NET MVC and SignalR.
1. We will host the signalR service in asp.net mvc4 web application.
2. Create a new asp.net MVC4 project in visual studio:
3. Install SignalR server in the project using package manager console
Install-Package Microsoft.AspNet.SignalR -Version 1.2.2
4. Create new folder "SignalR" in the project and add a class called as "MyConnection.cs" to the project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace IoT.Mobile.SignalR
{
public class MyConnection : PersistentConnection
{
protected override Task OnConnected(IRequest request, string connectionId)
{
return Connection.Broadcast(string.Empty);
}
protected override Task OnReceived(IRequest request, string connectionId, string data)
{
string msg = string.Format(
"{0},{1}", request.QueryString["name"], data);
return Connection.Broadcast(msg);
}
}
}
above class simply broadcasts all the messages recieved to the client.
Part III Building mobile web application for interacting with web api service
1. In previously created MVC4 web application we will create a controller called as "HomeController" and then add a view "Index.cshtml",
the view "Index.cshtml" contains radio buttons for turning the lights on and off and the code for calling signalR service.
@{
ViewBag.Title = "Control Home - IoT Azure";
}
<table class="ui-widget ui-widget-content">
<tr>
<td colspan="2" class="ui-widget-header">@ViewBag.Title</td>
<tr>
<td style="padding:10px">
Lights:
</td>
<td style="padding:10px">
<div id="radio">
<input type="radio" class="radio" id="radio1" name="radio"><label for="radio1">On</label>
<input type="radio" class="radio" id="radio2" name="radio" checked="checked"><label for="radio2">Off</label>
</div>
</td>
</tr>
</table>
<br/>
<br/>
Debug info:
<ul id="messages"></ul>
@section scripts
{
<script type="text/javascript">
function htmlEncode(value) {
return $("<div/>").text(value).html();
}
function addMsg(msg) {
if (msg != "") {
$("#messages").append("<li>" + htmlEncode(msg) + "</li>");
}
}
$(function() {
var connection = $.connection("/echo", "name=Server", true);;
connection.received(function(data) {
addMsg(data);
});
connection.error(function(err) {
addMsg("Error: " + err);
});
addMsg("Connecting...");
connection.start(function() {
addMsg("Connected.");
});
$("#radio").buttonset();
$('#radio').change(function () {
var $this = $('.radio:checked');
if ($this.attr("id")=="radio1") {
connection.send("turnon,com4");
} else {
connection.send("turnoff,com4");
}
});
});
</script>
}
<add key="ServiceUri" value="http://insteoniot.azurewebsites.net/echo"></add>
HARDWARE/SOFTWARE SETUP
1. Connect the insteon 2413U with Minix neo z64 windows mini PC using USB cable
2. Install windows service on the Minix Neo z64 windows mini pc using command line
IoT.WindowsService.exe install
3. Host the mobile app in cloud using Windows Azure Cloud Hosting,
4. The site is published at: http://insteoniot.azurewebsites.net
REFERENCES
1. FluentDwelling: http://soapboxautomation.com/products/fluentdwelling/
2. SignalR Tutorial: http://www.codeproject.com/Articles/633378/ASP-NET-SignalR-Basis-Step-by-Step-Part
3. Minix Neo Z64: http://www.minix.com.hk/Products/MINIX-NEO-Z64-WIN-PC.html
4. Insteon 2413U: http://www.amazon.com/Insteon-2413U-PowerLinc-Dual-Band-Interface/dp/B002XA8XNQ