SharpGIS

#GIS from a .NET developer's perspective

Announcing the first official OpenZWave library for UWP

As a follow-up to my recent OpenZWave blogpost ( http://www.sharpgis.net/post/2017/01/20/Using-OpenZWave-in-UWP-apps ), a few things has happened since.

First of all I’ve worked closely with the OpenZWave team, and we agreed to consolidate efforts. My library is now the official OpenZWave library for .NET and UWP, and has been moved out under the OpenZWave organization on GitHub:

       https://github.com/OpenZWave/openzwave-dotnet-uwp

At the same time the older .NET library has been removed from the main OpenZWave repository, so they can focus on the native parts of the library, and I’ve taken over the .NET effort.

To successfully support UWP and .NET, I wanted to achieve as close code compatibility as possible, and for maintainability also reuse as much C++ code as possible (both libraries are written in C++ – C++/CX for UWP and C++/CLI for .NET). The APIs for the two binaries should however be completely identical and the code you write against them the same. This meant a lot of refactoring, and breaking the original .NET a little. At the same time, I did a full API review, and cleaned it up to better follow the .NET naming guidelines. The overall API design hasn’t changed too much, and moving from the older .NET API shouldn’t be too much work (the original WinForms sample app was ported over with relatively little effort and is available in the repo as a reference as well).

However because of the many small breaking changes, the nuget package needs a major version increase.  I’ve just released the v2.0.0-beta1 package for you to start using. The API is release quality though, and should be very close to a final release. If you’ve done any OpenZWave dev, I encourage you to try it out and provide feedback.

Read the WIKI to see how to get started: https://github.com/OpenZWave/openzwave-dotnet-uwp/wiki

Or try out the sample applications included in the repository. So go grab the nuget package today and start Z-Waving!

                https://www.nuget.org/packages/OpenZWave/2.0.0-beta1

Note: If you are using IoTCore, beware that Microsoft pre-installs an OpenZWave to AllJoyn bridge. This bridge will grab your Serial Port, so make sure you disable this app prior to using the library. Second: The built in AllJoyn-ZWave service by Microsoft only supports the older Gen2 AeoTec adapter, whereas this library also works great with the Gen5 models.

Using OpenZWave in UWP apps

In my recent IoTivity hacking, I wanted to create a bridge between ZWave and IoTivity, and run it as a StartUp task on my Raspberry.

Something similar already exists in Windows IoT Core, as a bridge between ZWave and AllJoyn. Actually all you have to do is get a Generation 2 Aeotec ZWave ZStick, plug it into your device running IoT COre and you got yourself a ZWave-to-AllJoyn bridge. Unfortunately those aren’t being sold any longer, only the Generation 5, which isn’t compatible with the bridge. AllJoyn isn’t doing too well either.

Anyway, back to IoTivity: To build a bridge, I needed a ZWave library that supports UWP. After all, most of my devices are ZWave devices. I have my SmartThings hub as a primary controller, but you can add any number of ZWave USB Sticks as secondary controllers to the ZWave network. So I can continue to rely on SmartThings (for now), while I start hacking with the USB controller against the same devices.

Luckily Donald Hanson has an awesome pull-request for OpenZWave that adds a native UWP wrapper around OpenZWave, based on the .NET CLI wrapper. However the OpenZWave people were a little reluctant to merge it, as they already have a hard time maintaining the .NET CLI one, and suggested someone taking it over. I offered to do this but haven’t heard anything back from them. So while waiting, I just started a new repo to get going with Donalds blessing. I’ve spent a lot of time cleaning up the code, as there was a lot of odd patterns in the old .NET library that created an odd .NET API to work with (for example there was Get* methods instead of properties, delegates instead of events, static types that aren’t static etc). I’m also working on bringing the .NET and WinRT core in sync, so the two could share the same source-code. I’m not there yet, but it is getting close. If you have some C++ experience, I could really use some help with the abstraction bits to make this simpler.

Bottom-line is I now have a functioning wrapper for OpenZWave that can be used for .NET and UWP, and it works with the new Gen5 ZStick! (and many others) There are many breaking changes though, so I don’t know if OpenZWave wants to bring this into their fold. If not, I’ll keep hacking away at it myself. I do expect to continue making a lot of breaking changes to simplify its use and make it more intuitive. Due to the nature of ZWave devices, you can’t always rely on an instant response from a device when it is trying to save battery, so it could be several minutes before you get a response (or never), so a simple async/await model doesn’t work that well.

Anyway go grab the source-code (make sure you get the submodule too), and try it out: https://github.com/dotMorten/openzwave-dotnet-uwp

Here’s how you start it up:

//Initialize
ZWMOptions.Instance.Initialize(); //Configure default options
ZWMOptions.Instance.Lock();       //Options must be locked before using
ZWManager.Instance.Initialize();  //Start up the manager
ZWManager.Instance.OnNotification += OnNodeNotification; //Start listening for node events

//Hook up the serial port
var serialPortSelector = Windows.Devices.SerialCommunication.SerialDevice.GetDeviceSelector();
var devices = await DeviceInformation.FindAllAsync(serialPortSelector);
var serialPort = devices.First().Id; //Adjust to pick the right port for your usb stick
ZWManager.Instance.AddDriver(serialPort); //Add the serial port (you can have multiple!)

 

The rest is in the Notification handler. Every time a node is found, changed, remove etc. an event is reported here, including responses to commands you send. Nodes are identified by the HomeID (one per usb controller), and by the NodeID. You use these two values to uniquely identify a node on your network, and can then oerform operations like changing properties via the ZWManager instance.

There’s a generic sample app you can use to find, interrogate and interact with the devices, or just learn from. Longer-term I’d like to build a simpler API on top of this to work with the devices. The Main ViewModel in the sample-app is in a way the beginnings of this.

And by all means, submit some pull requests!

 

IoTivity.NET – A Crossplatform .NET Wrapper

Since I’m a .NET developer who can’t be bothered with spending too much time in C++, what am I to do if I want to use the IoTivity library to expose and interact with devices on the OCF protocols? The SDKs provided are either C++, C, Java (Android) and Object-C (iOS). .NET is sorely missing (hint hint OCF!).

Well the key here is the C SDK. It provides the necessary export of methods to import them into C# using p/invoke. Even better this approach works in .NET, UWP, but even Xamarin Android, and Xamarin iOS (and probably more). So why not create a set of C# classes in a .NET Standard library that imports the methods, to call into the native library?

Yeah I couldn’t come up with a reason why not, so I did: https://github.com/dotMorten/IotivityDotNet

This is however a work in progress, but it already allows you to create, discover and interact with devices over the IoTivity protocol. Compared to the AllJoyn APIs, the IoTivity API is A LOT simpler. In fact you can create a device in a single line of code.

To use, first initialize the Iotivity service:

 IotivityNet.Service.Initialize(IotivityNet.ServiceMode.Client);

You can then search for device resources using Device Discovery:

var svc = new IotivityDotNet.DiscoverResource("/oic/res");
svc.ResourceDiscovered += (s, e) =>
{
    Console.WriteLine($"Device Discovered @ {e.Response.DeviceAddress}");
};
svc.Start();

When you're done, shut down the Iotivity service:

await IotivityNet.Service.Shutdown();

Look at the sample apps for examples how to create devices to discover and respond to requests from clients.

 

Note 1: Currently the SDK is building off a fork of mine that has a set of bug-fixes for IoTivity, rather than using the official builds. All of these bugs are logged and waiting to be fixed, but the IoTivity maintainers have been pretty responsive to this, and one has already been fixed recently.

 

Note 2: Xamarin doesn’t work at this point. I have not been able to compile the native libraries for these platforms. However it should “just work” once that’s done. If you’re interested and have experience building native iOS and Android libraries, I would love a hand with it.

Is AllJoyn dead?

I’ve spent a lot of time the past two years building various AllJoyn related libraries and services. In fact every single smart-device in my home is accessible via AllJoyn. Most of that work is available as a set of repos on GitHub as well. However did I waste my time doing this? (apart from the fun it is). Here’s my take on all of this. It’s written from my personal point of view focused on building a smart-home. I might be wrong, or my arguments doesn’t apply in other scenarios. But please do use the comment section to add additional viewpoints.

 

First of all what is AllJoyn? AllJoyn is a protocol and a set of standard interfaces to interact with your smart devices on the local network. It is (was?) meant to be the standard that unifies all the other IoT standards, either by directly implementing AllJoyn in the device, or providing Device Service Bridges (DSB) to translate a protocol to AllJoyn. I created several DSBs to bridge my range of devices into one common set of AllJoyn interfaces (LIFX, Philips Hue, EcoBee, ZWave, ZigBee HA, ZigBee SE, etc). This was neat because I for instance didn’t have to care what type of light I was controlling. The code to discover, flip the switch, dim or change color would be the same. And if a new device/protocol came out tomorrow, my apps didn’t have to change, as long as a bridge was created.

However AllJoyn isn’t the only standard trying to do this, Open Connectivity Foundation started by Intel had similar goals, albeit some years behind on the implementation. It started to look like the Betamax/VHS wars all over, but luckily they decided to join forces and merge into one organization.

However it looks as if the direction going forward is betting on OCF’s protocol and it’s “Iotivity” open-source reference implementation, rather than the (slightly) more established AllJoyn protocol. So does that mean AllJoyn is dead? It’s a question people are very reluctant to give you a clear answer to. Here’s why I think that is:

1. AllJoyn already ships as part of Windows 10. Microsoft are pretty good at supporting their products and features for several years.

2. AllJoyn is still seeing development (regular commits are still going).

3. OCF will provide an AllJoyn to OCF bridge, and bring the two standards closer, taking the best of both.

 

Now I don’t have any knowledge what’s really happening with AllJoyn and it’s future, but here are my thoughts from an outside perspective:

Microsoft will often bring up #1 when asked about the future of AllJoyn. However I don’t read much into this. Their support lifecycle makes them required to support it for a while. It’s just part of their support life-cycle. However I find it doubtful that we’ll see Microsoft pushing forward with more AllJoyn support beyond what’s already there. They might update the binary with the latest versions, but I doubt we’ll see anything beyond that. Judging from Microsoft’s AllJoyn repos on GitHub, they are very clear they don’t have the resources to maintain/improve them. For instance see this comment. Judging from the IoTivity committers and its developer mailinglist, it’s the same people from Microsoft who also contributed to AllJoyn, so it’s fair to assume resources has been moved away from AllJoyn towards IoTivity.

OCF are saying they’ll provide a bridge, and it’s on the timeline for v2.0 due in April. However looking at how different the specs are and how differently devices are exposed, I’m guessing the bridge will be exposing AllJoyn devices to IoTivity in such a generic way it becomes virtually use-less (but would love to be proved wrong). Yes there might be a boolean exposed that flips the switch on a light, but if the object isn’t actually modeled as a device that looks like any other “proper” IoTivity light, but just a set of generic properties, it doesn’t really help us to create a great user-interface for controlling all our devices. We’ll have to see, but the bridge feels and smells like a temporary band-aid until everyone is moved over. And let’s be honest… there really aren’t that many AllJoyn devices to bridge.

I’ve also seen the merger to cause a little bit of a split within the AllSeen Alliance members. Some people do not like the OCF licensing and find it too restrictive. Other people find the merger more important, since it brings a lot of big players on board, like Samsung and Intel. This split doesn’t bode well for AllJoyn, and the concerns doesn’t really affect you and I who just want to talk to these devices with out apps, bots, dashboards, etc.

AllJoyn might be more mature, but the only wide-ranging consumer product that shipped with AllJoyn was the LIFX light bulb, and LIFX aren’t even betting much more on AllJoyn1. Yes there are more products, like various music players, humidifiers etc (and all with a horrible ecosystem to control them), but you’ll be hard pressed finding any other Alljoyn products selilng in significant numbers, and none of them implement a standard set of useable interfaces. The AllSeen Alliance likes to bring up that they have over 325 millions devices that support AllJoyn, but they are including Windows 10, which while having an AllJoyn routing service installed, really shouldn’t be counted as an AllJoyn device. The fact is AllJoyn sadly never really caught on.

 

So based on this, is AllJoyn dead and should you switch to bet on IoTivity: YES! (sorry guys, but someone had to say it).

Will IoTivity be a waste of time and die off soon: I seriously doubt it. All the right players are part of this, and I don’t really see any other serious contender trying to solve this problem.

If you already have AllJoyn products shipped, you should be ok for a bit. However creating a new product today based on AllJoyn seems really senseless. Personally I’ve stopped all my AllJoyn development, and starting building a .NET Standard wrapper around the IoTivity APIs (help wanted!). Unless you control your entire internal eco-system and use AllJoyn to communicate between them (it’s really great/simple for this) consider your AllJoyn work a sunk cost and just move on already.

 

Disagree or have additional insights to share? Please write in the comment section.

 

1) Quote from LIFX VP: “We're dependent on chipset providers for our AJ [Alljoyn] support, and their focus has somewhat shifted elsewhere of late, as the market evolves and consolidates.”. Also long-time reported AllJoyn bugs aren’t getting fixed by LIFX, indicating that they have no commitment to AllJoyn.

IoT Series

Yes yes yes, I know… this blog has been pretty quiet lately. Sorry, I’m trying to fix this. I’ve been busy with releasing a very large awesome .NET product, spending some time on the UWP Community Toolkit, and hacking away at various IoT projects, and most importantly spending time with my family. My IoT-related GitHub repos are getting a little out of hand, but I’m having a lot of fun creating all the building blocks for a smart-home. My ultimate goal is to build a system that can interact with any protocol, and is resilient against internet-outages (your light switch should still work even if the internet is down – yes I’m looking at you SmartThings!).

Regarding my IoT projects, I’d like to start writing down my progress, make some notes, ramblings etc. It’s a great way to get feedback, share your work, gather your own thoughts, and having to explain something helps myself really understanding the topic etc. So I’d like to start my blog back up with various IoT topics. For those who have been following me on twitter knows I’ve been hacking away at AllJoyn, ZigBee, ZWave, IoTivity etc. I’m going to start writing some blogposts gathering my experiences, thoughts etc.

While this blog might have been a little quiet, I have actually been writing some articles on Hackster.io, so I’ll start with a few links to those, before diving into a series of IoT related blogposts.

Stay tuned….

Running a .NET app on Galileo using Mono

In my first blog post on my home automation project, I mentioned that the ultimate goal was to run it all on a Galileo, but since .NET isn’t really supported yet, this wasn’t an option. Too the rescue comes Jer with his Mono port, allowing you to run .NET console apps on the Galileo. You can read the details on this on his blog post here: http://jeremiahmorrill.wordpress.com/2014/08/31/mono-on-windows-iot-galileo/

In my second blog post, I wrote a little console app that acts as a small webserver that allows Windows Store and Windows Phone apps to register themselves as a push target, and the console app can send push messages to these apps. In this blog post we’ll use Jer’s mono hack to get this running on the Galileo.

First, we need to “install” mono on Galileo. Jump to Jer’s blog post and grab the mono_iot.zip file at the bottom of his blog post. Next unzip this file to the Galileo in a root folder like \mono\. You can access the Galileo in a network path by adding \c$\ to the network path. Ie. unzip into: \\mygalileo\c$\mono\ (if your device name is ‘mygalileo’ or replace it with the name or IP number). If you haven’t done this before, you’ll be prompted for username/password. Enter “mygalileo\Administrator” and your admin password. That’s really all that’s required for ‘installing’ mono.

Now to run a .NET app, all you have to do is call [path-to-mono.exe] [path-to-my-app.exe] to launch the app with the mono runtime. Almost any .NET console app will work. Ie:

c:\mono\bin\mono.exe c:\sampleapp\ConsoleApp1.exe

Next, we’ll run the push service app from my previous blog post. Compile the PushService app (yes you can use Visual Studio – no need for the Mono compiler) and copy it to the Galileo. Then open a Telnet terminal to Galileo, and start the service:

c:\mono\bin\mono.exe c:\PushService\PushService.exe

Next, update the client store/phone app to point to the IP of your galileo device, and make sure it’s on the same network. When running the app, you should now be able to register with the push service.

image

CTRL-Q to quit doesn’t seem to work. I’m guessing the CTRL key isn’t sent via telnet. You can just hit CTRL-C to quit the app.

Also if you press “S” to push a message, you’ll notice that the app fails. This is because the push notification hits an SSL secured server, and Mono doesn’t come with any SSL roots certificates installed. An in-depth article is describing this here: http://www.mono-project.com/docs/faq/security/ and here: http://www.mono-project.com/archived/usingtrustedrootsrespectfully/ . Note though that the current Mono build you installed doesn’t seem to work for the certificate imports, so most of the solutions might not work for you. As a TEMPORARY alternative, we can get rid of the SSL certificate validation. Note: This is quite dangerous and should NOT be used in production. But for testing this is fine (if you think this is not a big deal, think again – iOS and MacOS had this issue recently and it was a MAJOR security problem). To disable validation, we basically just take over validation and return ‘true’ to say the certificate is fine regardless of it’s contents. You could also enhance this yourself by performing your own validation. To do this, all we need to add is the following line of code when the console app starts up:

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Now redeploy the app, and you can now get your Galileo to perform push messages straight to your phone or tablet! How cool is that???

image

This is all the starting pieces you need to build a small simple .NET based webserver for controlling your Galileo. At the same time it’s all you need for getting your Galileo to notify you of certain events occurring. Bottom line: It’s the first big step into a .NET based home automation controller. The next big step is to create the building blocks for a trigger –> event system, so we can start automating and monitoring our home with the power of .NET and Windows on Devices.

Creating a simple push service for home automation alerts

In my intro post for my home automation project, I described a part of the app that sends temperature, humidity and power consumption measurements and pushes them to my phone. In this blogpost, we’ll build a simple console-webservice that allows a phone to register itself with the service, and the service can push a message to any registered device using the Windows Notification Service. Even if you’re not building a home automation server, but just need to figure out how to push a message to your phone or tablet, this blogpost is still for you (but you can ignore some of the console webservice bits).

To send a push message via WNS to an app, you need the “phone number of the app”. This is a combination of the app and the device ID. If you know this, and you’re the owner for the app, you are able to push messages to the app on the device. It’s only the app on the device that knows this phone number. If the app wants someone to push a message to the device, it will need go share it with that someone. But for this to work, you will first have to register the app on the Microsoft developer portal and associate your project with the app in order to be able to create a valid “phone number”.

Here’s the website after registering my app “Push_Test_App”. You simply create a new app, and only need to complete step 1 to start using WNS.

image

Next you will need to associate your app with the app you created in the store from the following menu item:

image

Simply follow the step-by-step guide. Note that the option is only available for the active startup-up project. Repeat this for both the store and phone app if you’re creating a universal project (make sure to change the startup project to get the menu item to relate to the correct project).

This is all we need to do to get the app’s “phone number”  the “channel uri”. We can get that using the following line of code:

var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var uri = channel.Uri;

Notice that the channel.Uri property is just a URL. This is the URL to the WNS service where we can post stuff to. The WNS service will then forward the message you send to your app on the specific device.

Next step is to create a push service. We’ll create two operations: A webservice that an app can send the channel Uri to, and later an operation to push messages to all registered clients.

We’ll first build the simple console app webserver. Some of this is in part based http://codehosting.net/blog/BlogEngine/post/Simple-C-Web-Server.aspx where you can get more details.

The main part to notice is that we’ll start a server on port 8080, and we���ll wait for a call to /registerPush with a POST body containing a json object with channel uri and device id:

using System;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Threading;

namespace PushService
{
    internal class HttpWebService
    {
        private HttpListener m_server;
        
        public void Start()
        {
            ThreadPool.QueueUserWorkItem((o) => RunServer());
        }

        private void RunServer()
        {
            Int32 port = 8080;
            m_server = new HttpListener();
            m_server.Prefixes.Add(string.Format("http://*:{0}/", port));
            m_server.Start();
            while (m_server.IsListening)
            {
                HttpListenerContext ctx = m_server.GetContext();
                ThreadPool.QueueUserWorkItem((object c) => ProcessRequest((HttpListenerContext)c), ctx);
            }
        }

        public void Stop()
        {
            if (m_server != null)
            {
                m_server.Stop();
                m_server.Close();
            }
        }

        private void ProcessRequest(HttpListenerContext context)
        {
            switch(context.Request.Url.AbsolutePath)
            {
                case "/registerPush":
                    HandlePushRegistration(context);
                    break;
                default:
                    context.Response.StatusCode = 404; //NOT FOUND
                    break;
            }
            context.Response.OutputStream.Close();
        }

        private void HandlePushRegistration(HttpListenerContext context)
        {
            if (context.Request.HttpMethod == "POST")
            {
                if (context.Request.HasEntityBody)
                {
                    System.IO.Stream body = context.Request.InputStream;
                    System.Text.Encoding encoding = context.Request.ContentEncoding;
                    System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
                    DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(RegistrationPacket));
                    var packet = s.ReadObject(reader.BaseStream) as RegistrationPacket;
                    if (packet != null && packet.deviceId != null && !string.IsNullOrWhiteSpace(packet.channelUri))
                    {
                        if (ClientRegistered != null)
                            ClientRegistered(this, packet);
                        context.Response.StatusCode = 200; //OK
                        return;
                    }
                }
            }
            context.Response.StatusCode = 500; //Server Error
        }

        /// <summary>
        /// Fired when a device registers itself
        /// </summary>
        public event EventHandler<RegistrationPacket> ClientRegistered;


        [DataContract]
        public class RegistrationPacket
        {
            [DataMember]
            public string channelUri { get; set; }
            [DataMember]
            public string deviceId { get; set; }
        }
    }
}

Next let’s start this service in the console main app. We’ll listen for clients registering and store them in a dictionary.

 

private static Dictionary<string, Uri> registeredClients = new Dictionary<string, Uri>(); //List of registered devices

static void Main(string[] args)
{
    //Start http service
    var svc = new HttpWebService();
    svc.Start();
    svc.ClientRegistered += svc_ClientRegistered;

    Console.WriteLine("Service started. Press CTRL-Q to quit.");
    while (true)
    {
        var key = Console.ReadKey();
        if (key.Key == ConsoleKey.Q && key.Modifiers == ConsoleModifiers.Control)
            break;
    }
    //shut down
    svc.Stop();
}
        
private static void svc_ClientRegistered(object sender, HttpWebService.RegistrationPacket e)
{
    if(registeredClients.ContainsKey(e.deviceId))
        Console.WriteLine("Client updated: " + e.deviceId);
    else
        Console.WriteLine("Client registered: " + e.deviceId);
    
    registeredClients[e.deviceId] = new Uri(e.channelUri); //store list of registered devices
}

Note: You will need to launch this console app as admin to be able to open the http port.

Next, let’s add some code to our phone/store app that calls the endpoint and sends its channel uri and device id (we won’t really need the device id, but it’s a nice way to identify the clients we have to push to and avoid duplicates). We’ll also add a bit of code to handle receiving a push notification if the server was to send a message back (we’ll get to the latter later):

private async void ButtonRegister_Click(object sender, RoutedEventArgs e)
{
    var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    var uri = channel.Uri;
    channel.PushNotificationReceived += channel_PushNotificationReceived;
    RegisterWithServer(uri);
}

private async void RegisterWithServer(string uri)
{
    string IP = "192.168.1.17"; //IP address of server. Replace with the ip/servername where your service is running on
    HttpClient client = new HttpClient();

    DataContractJsonSerializer s = new DataContractJsonSerializer(typeof(RegistrationPacket));
    RegistrationPacket packet = new RegistrationPacket()
    {
        channelUri = uri,
        deviceId = GetHardwareId()
    };
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    s.WriteObject(ms, packet);
    ms.Seek(0, System.IO.SeekOrigin.Begin);
    try
    {
        //Send push channel to server
        var result = await client.PostAsync(new Uri("http://" + IP + ":8080/registerPush"), new StreamContent(ms));
        Status.Text = "Push registration successfull";
    }
    catch(System.Exception ex) {
        Status.Text = "Push registration failed: " + ex.Message;
    }
}

//returns a unique hardware id
private string GetHardwareId()
{
    var token = Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null);
    var hardwareId = token.Id;
    var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);

    byte[] bytes = new byte[hardwareId.Length];
    dataReader.ReadBytes(bytes);
    return BitConverter.ToString(bytes);
}

[DataContract]
public class RegistrationPacket
{
    [DataMember]
    public string channelUri { get; set; }
    [DataMember]
    public string deviceId { get; set; }
}

//Called if a push notification is sent while the app is running
private void channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
{
    var content = args.RawNotification.Content;
    var _ = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        Status.Text = "Received: " + content; //Output message to a TextBlock
    });
}

Now if we run this app, we can register the device with you service. When you run both, you should see a “client registered” output in the console. If not, check your IP and firewall settings.

Lastly, we need to perform a push notification. The basics of it is to simply post some content to the url. However the service will need to authenticate itself using OAuth. To authenticate, we need to go back to the dev portal and go to the app we created. Click the “Services” option:

image

Next, go to the subtle link on the following page (this link isn’t very obvious, even though it’s the most important thing on this page):

image

The next page has what you need. Copy the highlighted Package SID + Client Secret on this page. You will need this to authenticate with the WNS service.

image

The following helper class creates an OAuth token using the above secret and client id, as well as provides a method for pushing a message to a channel uri using that token:

using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;

namespace PushService
{
    internal static class PushHelper
    {
        public static void Push(Uri uri, OAuthToken accessToken, string message)
        {
            HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
            request.Method = "POST";
            //Change this depending on the type of notification you need to do. Raw is just text
            string notificationType = "wns/raw";
            string contentType = "application/octet-stream";
            request.Headers.Add("X-WNS-Type", notificationType);
            request.ContentType = contentType;
            request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

            byte[] contentInBytes = Encoding.UTF8.GetBytes(message);
            using (Stream requestStream = request.GetRequestStream())
                requestStream.Write(contentInBytes, 0, contentInBytes.Length);
            try
            {
                using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
                {
                    string code = webResponse.StatusCode.ToString();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static OAuthToken GetAccessToken(string secret, string sid)
        {
            var urlEncodedSecret = HttpUtility.UrlEncode(secret);
            var urlEncodedSid = HttpUtility.UrlEncode(sid);

            var body =
              String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com", urlEncodedSid, urlEncodedSecret);

            string response;
            using (var client = new System.Net.WebClient())
            {
                client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                response = client.UploadString("https://login.live.com/accesstoken.srf", body);
            }
            using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(response)))
            {
                var ser = new DataContractJsonSerializer(typeof(OAuthToken));
                var oAuthToken = (OAuthToken)ser.ReadObject(ms);
                return oAuthToken;
            }
        }
    }

    [DataContract]
    internal class OAuthToken
    {
        [DataMember(Name = "access_token")]
        public string AccessToken { get; set; }
        [DataMember(Name = "token_type")]
        public string TokenType { get; set; }
    }
}

Next let’s change our console main method to include pushing a message to all registered clients when pressing ‘S’. In this simple sample we’ll just push the current server time.

static void Main(string[] args)
{
    //Start http service
    var svc = new HttpWebService();
    svc.Start();
    svc.ClientRegistered += svc_ClientRegistered;

    Console.WriteLine("Service started. Press CTRL-Q to quit.\nPress 'S' to push a message.");
    while (true)
    {
        var key = Console.ReadKey();
        if (key.Key == ConsoleKey.Q && key.Modifiers == ConsoleModifiers.Control)
            break;
        else if(key.Key == ConsoleKey.S)
        {
            Console.WriteLine();
            PushMessageToClients();
        }
    }
    //shut down
    svc.Stop();
}

private static void PushMessageToClients()
{
    if (registeredClients.Count == 0)
        return; //no one to push to

    //Message to send to all clients
    var message = string.Format("{{\"Message\":\"Current server time is: {0}\"}}", DateTime.Now);

    //Generate token for push

    //Set app package SID and client clientSecret (get these for your app from the developer portal)
    string packageSid = "ms-app://s-X-XX-X-XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX";
    string clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    //Generate oauth token required to push messages to client
    OAuthToken accessToken = null;
    try
    {
        accessToken = PushHelper.GetAccessToken(clientSecret, packageSid);
    }
    catch (Exception ex)
    {
        Console.WriteLine("ERROR: Failed to get access token for push : {0}", ex.Message);
        return;
    }

    int counter = 0;
    //Push the message to all the clients
    foreach(var client in registeredClients)
    {
        try
        {
            PushHelper.Push(client.Value, accessToken, message);
            counter++;
        }
        catch (Exception ex)
        {
            Console.WriteLine("ERROR: Failed to push to {0}: {1}", client.Key, ex.Message);
        }
    }
    Console.WriteLine("Pushed successfully to {0} client(s)", counter);
}

Now run the console app and the phone/store app. First click the “register” button in your app, then in the console app click “S” to send a message. Almost instantly you should see the server time printed inside your app.

image

 

Note: We’re not using a background task, so this will only work while the app is running. In the next blogpost we’ll look at how to set this up, as well as how to create a live tile with a graph on it.

You can download all the source code here: Download (Remember to update the Packet SID/Client Secret and associate the app with your own store app).

Internet of Things blog series

For those who have been following me on twitter, you might have noticed I’ve been playing a lot with home automation lately. I’m planning on blogging about my experiences, and how some of the pieces are put together. At this point it’s far from a full solution – just a lot of pieces and custom ugly code wired together to get some things going. In the long term, I hope to have a fully configurable and extensible home automation system, but that would probably take me a few years to get there. This is the first in a series of blogs about my experiences, and why I’m doing it the way I am. I would love to hear your inputs and ideas in the comments.

In this first post I’m going to talk about what hardware my system consists off.

Devices, protocols etc.

There’s a lot of “internet of things” devices out there already today. Unfortunately there’s also a lot of standards. And a lot of competition to get the standards to succeed. It’s like the VHS vs Betamax wars right now. Any or all might win. And some systems supports multiple. Of some of the main ones on the market today:

  1. Insteon / X10
  2. Z-Wave
  3. Zigbee

These standards allow devices to talk together using a common protocol, but they usually need a hub or bridge to configure it all. Several companies have then built controller hubs or bridges on top of these standards. This is where I think the entire system starts breaking down: Each company doesn’t want to help the other company, and that means each company has their own standards for talking to the controller, their website or no API at all. Another thing I’ve noticed: Most of these systems only work if you’re connected to the internet (if so the controller is usually called a “gateway”). If your internet is down you suddenly can’t control your house, your sprinklers might not run, AC is inoperable etc. And you also put a lot of trust in to that company’s security. The Heartbleed drama is a good example of why I find this really concerning. Especially considering that from their website you can see if anyone is home, disable the alarm and cameras and unlock the door, then put it all back in place as if nothing happened when they are done robbing your house. Add to that, that many controllers only works connected if you also purchase a subscription.

Lastly because all the controllers that do offer APIs, are all different. That means if I were to build a Home Automation App, I would have to either choose one of the controllers and have vendor-lock-in, meaning I would severely reduce the number of people who could use my app. Or I would have to buy all the controllers out there and build an abstraction layer. Neither of this I found very appealing either – especially considering the winning standards is still unknown.

So instead I started something else: I created my own controller software, and started to put some abstraction in into it, and uses MEF to allow extending it with more controllers – allowing others to contribute with plugins. The controller service software runs on my home PC, and is running completely offline. It’s really an “Intranet of Things”. When my phone is on the home wifi, it can talk directly to the server, and register for push updates, and the server software can push notifications to my phone, even when I’m not on the wifi. This allows me to do one-way monitoring of my phone. And if I need direct access, I can always VPN home. Lastly by not relying on a server online, I don’t have to pay, manage, scale, deal-with, build, setup etc any cloud services. It’s all self-contained – however it doesn’t prevent me from pushing data out on the internet, or connecting to a cloud service if I really wanted to.

I recently got a Galileo device, and ultimately I want to make this service run on this: image

This is just a command-line version of Windows running on a really cheap piece of hardware. That means anyone could use my server software very cheap, or just install it on a PC. Well… that’s the long term plan anyway. The WindowsOnDevices version is still in its early stages and doesn’t have everything I need yet. So for now, it runs on my PC.

The hardware I’m using

I settled on the Zigbee standard for myself (for now). I like some of the promises of Zigbee as well as some of the supported devices out there. Some of the reasons I went with Zigbee:

  • Zigbee is an extremely low-power mesh network. The mesh network means the more devices you have, the better/stronger network you have. Some devices can run 10 years on a tiny battery.
  • A lot of utility companies have chosen this standard to allow you to read your power consumption real-time as well as current KwH cost, total consumption etc.
  • More and more companies seems to be adding support for it, meaning device prices are slowly coming down.
  • Philips Hue lights uses Zigbee (these lights are cool!).
  • The Nest Thermostat has a zigbee radio - not yet(?) enabled though. I’m keeping my fingers crossed…
  • A friend of mine gave me a Zigbee USB controller Smile
  • The USB controller I got works directly with the Zigbee network giving me full very fine-grained control (but see cons further down)

There are some cons with Zigbee too though.

  • License cost for Zigbee means the devices can be a little pricy.
  • There’s several sub-standards. Zigbee HA is for home automation. Zigbee SE is a more secure version used for your smart meters. You’ll need two separate controllers to monitor both (at least they are very similar to talk to though).
  • The standard is very flexible, which means it’s also pretty complex. Some controllers abstracts this away though (not mine).
  • In addition there’s a new “light link” standard for HA that the Philips Hue lights run on – I believe this allow it to run controller-less. Unfortunately my HA controller doesn’t support Light Link, and the manufacturer still hasn’t updated the firmware (which btw I can’t even update myself).
  • The USB Controller (or ‘coordinator’ in ZigBee speak) I have is using a VERY low-level API. It’s a lot of bit-wise operators and working with raw binary data coming in and out. It was a LOT of work just getting it working somewhat. And if you choose a different controller, most or none of my zigbee code is re-useable.

Here’s a picture of a door/window sensor, the USB coordinator and a temperature/humidity sensor.

image

The door sensor only uses power when it opens or closes – it’s estimated battery life is 10 years. The Temp/Humidity sensor reports measurements every 3 mins (configurable), and should last about 3 years. I have a a couple of these, plus more door sensors on the way, as well as a Philips Hue light bulb.

At this point, I wrote a little piece of software of my PC that monitors messages coming in on the ZigBee network, and turns them into push notifications. It creates a nice live-tile graph of temperature , humidity (inside and out) and recent power consumption (I’ll blog about this in a later article).

image

It even allows me to configure alerts when a value exceeds a certain level:

image

This is actually very useful when I brew beer. Since I don’t have a temperature-controlled brew-keg, this is the second best. I put the sensor in with the keg, and I get alerts on my phone when the wort is too hot or cold.

image

I addition I can also monitor my power consumption using a separate (but similar) Zigbee SE receiver. It sends the same graph to my phone, but my local app monitors changes in usage down to the second (I push the usage graph a lot rarer to save phone battery). It’s interesting to see what uses power and not, and how much drain it causes. You can actually see a light turn on, or when the fridge thermostat turns on and off. It’s very educational about your power consumption, and how much standby power you use. You can also read what the current cost of electricity is to help you make certain decisions.

image

I also recorded a video of this here: 1liLQbq. You can see the graph jump 1-2 seconds after I turn a light on or off.

Some of the code for working with the Zigbee USB receiver I’ve put on Github – it’s still in a slightly rough state though: https://github.com/dotMorten/ZigbeeNet

More devices…

California is in a severe drought right now. That means there’s a lot of water restrictions in effect, including what days you can water, and what types of watering you’re allowed to do. The sprinkler time I had couldn’t automatically do this, so I just bought a new one. OpenSprinkler which is an open-source Arduino based controller. It can connect to the local network and be remotely controlled. It even has a little REST API (albeit fairly undocumented but source code is available for reverse engineering).

image

While the software and web interface is pretty simple, it actually works very well. It even has a Windows Phone and Windows store app (based on Cordova). I’ve also started a little project to build a .NET API for this controller so I can integrate it into my “system”. Source-code for that is all available on Github: https://github.com/dotMorten/OpenSprinklerNet

I also have a couple of ZigBee-supported AC thermostats on the way, as well as some better and prettier window sensors that I would actually considering putting up (it’s beyond me why anyone would make such an ugly sensor to mount on all windows).

What’s next

I want to build an “If this then that” style configuration for my server software. Currently all I can do is push measurements out. Next is to set up rules and make things happen with the rules are satisfied. For example “If air condition is running and a window is open, send alert”. Or “If phone/me leaves the house and a window is open, alert” Or “if it was hot, windy and dry yesterday, increase lawn watering”. Or “If outside temperature and humidity is at a certain level and inside humidity doesn’t exceed a certain level, switch from air condition to swamp cooler”.  The last example is actually what got me started: I have two air condition units (upstairs and downstairs), 5 whole-house fans, and two swamp-coolers. What’s more efficient to run (or combination thereof), is quite tricky and also depends on outside and inside conditions. I live in a very old house with really poor insulation, so choosing the cheapest cooling system during the very hot summers here could save me a lot of money. A fancy rule-based system for making those decisions is what I really need. Add to that, I could tweak that decision making using weather forecasts, my current location (or my phone’s that is), and the current electricity cost.

And I want to make it pluggable. It shouldn’t just be Zigbee, or just the devices I have. I want to make it so that you can quickly add more devices and protocols by adding a plugin. It’s definitely quite a software engineering task – if you have some experience with this, I’d love to hear your design ideas. I’ll put it all on Github for people to use – and hopefully to contribute.

Then next, would be getting it all to run on the Galileo board, but there’s still some .NET and USB support lacking so for now it’ll run on a PC.

It’s a big task – it’ll take some work and time. So in the mean time I’ll be blogging about how some of the pieces are built. Stay tuned…