{"id":1907,"date":"2016-06-14T07:53:25","date_gmt":"2016-06-14T06:53:25","guid":{"rendered":"http:\/\/blog.repsaj.nl\/?p=1907"},"modified":"2016-07-08T14:31:44","modified_gmt":"2016-07-08T13:31:44","slug":"iot-aquarium-monitor-sending-commands-back-to-your-hardware","status":"publish","type":"post","link":"http:\/\/blog.repsaj.nl\/index.php\/2016\/06\/iot-aquarium-monitor-sending-commands-back-to-your-hardware\/","title":{"rendered":"[IoT] Aquarium monitor; Sending commands back to your hardware"},"content":{"rendered":"<p>Let&#8217;s start with some awesome news first! All of the sources for this project are now live on GitHub! Which doesn&#8217;t mean I&#8217;m close to being finished by the way, but it does allow you to take a look and maybe even contribute should you want to. This includes all of the code from the <a href=\"http:\/\/blog.repsaj.nl\/index.php\/series\/azure-aquarium-monitor\/\" target=\"_blank\">previous blog posts<\/a> as well, so go over and take a look:<\/p>\n<p><a href=\"http:\/\/github.com\/jsiegmund\/submerged\" target=\"_blank\">http:\/\/github.com\/jsiegmund\/submerged<\/a><\/p>\n<p>Allright, so let&#8217;s get down to what this post is all about: sending commands back to your hardware.<!--more--><\/p>\n<h2>IoT Hub<\/h2>\n<p>As we saw in <a href=\"http:\/\/blog.repsaj.nl\/index.php\/2016\/01\/iot-aquarium-monitor-raspberry-azure-iot-hub\/\" target=\"_blank\">part three<\/a>, the Azure IoT hub is the central place for communicating with your devices. This doesn&#8217;t limit to data being sent\u00a0from the device to the cloud, but also includes messages from the cloud to the device. Appropriately named, the two message types are:<\/p>\n<ul>\n<li>Cloud to device<\/li>\n<li>Device to cloud<\/li>\n<\/ul>\n<p>Nice and simple, right? So let&#8217;s start sending and receiving some commands.<\/p>\n<h2>Setting up the receiver<\/h2>\n<p>The receiver in our scheme will be the Raspberry Pi running Windows 10. Sending and receiving messages from the cloud is it&#8217;s task being a gateway device. The code is actually quite simple:<\/p>\n<pre class=\"lang:default decode:true\">private async void ReceiveC2dAsync()\r\n{\r\n    while (true)\r\n    {\r\n        Message receivedMessage = null;\r\n\r\n        try\r\n        {\r\n            receivedMessage = await _deviceClient.ReceiveAsync();\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            \/\/ when something happens in the transport; reboot the client\r\n            _deviceClient = DeviceClient.CreateFromConnectionString(_deviceConnectionString);\r\n        }\r\n\r\n        if (receivedMessage == null) continue;\r\n\r\n        DeserializableCommand command = new DeserializableCommand(receivedMessage);\r\n        await CommandReceived(command);\r\n        await _deviceClient.CompleteAsync(receivedMessage);\r\n    }\r\n}<\/pre>\n<p>As you see this already includes some plubming and error handling. I found that sometimes the <strong>ReceiveAsync\u00a0<\/strong>call will fail (I have yet to find out why), so I&#8217;ve added some try\/catch logic to deal with that.<\/p>\n<p>The\u00a0<strong>ReceiveAsync<\/strong> call will not complete until the device actually receives a message, so you will probably want to run this in a seperate thread. As soon as the device receives a message, I translate that into a DeserializableCommand, which looks like this:<\/p>\n<pre class=\"lang:default decode:true \">public class DeserializableCommand\r\n{\r\n    private readonly dynamic _command;\r\n\r\n    public string CommandName\r\n    {\r\n        get { return _command.Name; }\r\n    }\r\n\r\n    public dynamic Command\r\n    {\r\n        get { return _command; }\r\n    }\r\n\r\n    public DeserializableCommand(Message message)\r\n    {\r\n        if (message == null)\r\n        {\r\n            throw new ArgumentNullException(\"message\");\r\n        }\r\n\r\n        byte[] messageBytes = message.GetBytes(); \/\/ this needs to be saved if needed later, because it can only be read once from the original Message\r\n        string jsonObject = Encoding.ASCII.GetString(messageBytes);\r\n        _command = JsonConvert.DeserializeObject&lt;dynamic&gt;(jsonObject);\r\n    }\r\n}<\/pre>\n<p>Nice and simple, right? The message is converted to a json string and then deserialized into the object it represents. The json command coming over the line should have a name, and the rest of the command depends on which command is being sent.<\/p>\n<p>That&#8217;s all there is to it on the receiving end. Of course you need some code handling the command you&#8217;re receiving, but that depends on your implementation. The Commands directory in the submerged source code will show you how I&#8217;ve done it.<\/p>\n<h2>Setting up the sender<\/h2>\n<p>The sender is doing equal things as you might have expected. A\u00a0similar\u00a0<strong>Command<\/strong> object is constructed, translated into json and then\u00a0converted into the bytes that will be sent across the wire.<\/p>\n<pre class=\"lang:default decode:true \">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Sends a fire and forget command to the device\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;param name=\"deviceId\"&gt;&lt;\/param&gt;\r\n\/\/\/ &lt;param name=\"command\"&gt;&lt;\/param&gt;\r\n\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\npublic async Task SendCommand(string deviceId, dynamic command)\r\n{\r\n    ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(_iotHubConnectionString);\r\n\r\n    byte[] commandAsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(command));\r\n    var notificationMessage = new Message(commandAsBytes);\r\n\r\n    notificationMessage.Ack = DeliveryAcknowledgement.Full;\r\n    notificationMessage.MessageId = command.MessageId;\r\n\r\n    await AzureRetryHelper.OperationWithBasicRetryAsync(async () =&gt;\r\n        await serviceClient.SendAsync(deviceId, notificationMessage));\r\n\r\n    await serviceClient.CloseAsync();\r\n}<\/pre>\n<p>The\u00a0<strong>serviceClient.Async<\/strong> part is where the magic happens. There&#8217;s some retry logic in place should things fail for whatever reason. Also notice how the message will request for delivery acknowledgement so that you know the message was received. The client will also make sure the command was successfully processed before returning the acknowlegdement, so you will know whether things succeeded or not.<\/p>\n<h2>Implementing commands<\/h2>\n<p>So the above is all you need to get communications going. The next part of course is to make sure these communications are meaningful and actually do something. In my case, I&#8217;ve got two types of commands set-up right now:<\/p>\n<ul>\n<li><strong>Configuration updates:<\/strong> whenever I change something that the gateway needs to know, I send an updated configuration to the device. Doing this will update the device in near real-time so that I do not have to reboot the app or something like that.<\/li>\n<li><strong>Relay switches.\u00a0<\/strong>I&#8217;ve modified an outlet strip to include a 4 channel relay board. This allows me to switch 4 of the 6 relays using another Arduino. So when a relay switch command is received, it&#8217;s transmitted to the Arduino which will carry out the command as a true soldier. This allows me to turn off\/on my filter, heating and lights.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/blog.repsaj.nl\/index.php\/2016\/06\/iot-aquarium-monitor-sending-commands-back-to-your-hardware\/img-20160505-wa0009\/\" rel=\"attachment wp-att-1908\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-large wp-image-1908\" src=\"http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009-576x1024.jpg\" alt=\"IMG-20160505-WA0009\" width=\"576\" height=\"1024\" srcset=\"http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009-576x1024.jpg 576w, http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009-169x300.jpg 169w, http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009-768x1366.jpg 768w, http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009-624x1110.jpg 624w, http:\/\/blog.repsaj.nl\/wp-content\/uploads\/2016\/06\/IMG-20160505-WA0009.jpg 899w\" sizes=\"(max-width: 576px) 100vw, 576px\" \/><\/a><\/p>\n<p>For anyone interested in the schematics and other hardware, I plan on making a used hardware list real soon!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s start with some awesome news first! All of the sources for this project are now live on GitHub! Which doesn&#8217;t mean I&#8217;m close to being finished by the way, but it does allow you to take a look and maybe even contribute should you want to. This includes all of the code from the<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[34],"tags":[78,150,39],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3KFR1-uL","_links":{"self":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts\/1907"}],"collection":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/comments?post=1907"}],"version-history":[{"count":0,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts\/1907\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/media?parent=1907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/categories?post=1907"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/tags?post=1907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}