Using Win10 Core and Azure IoT Services with Raspberry Pi2 – Part 2


This is Part 2 of the multi-part blog series Using Win10 Core and Azure IoT Services with Raspberry Pi2. For an introduction of the scenario, please refer here.

Developing an Azure IoT Service Connected Windows Universal app

In Part 1 of this blog series, we covered setting up the Pi and related modules for building and deploying our Windows universal app. In this blog post we will develop our app and then remotely deploy it the Pi device we configured.

If you do not have Visual Studio configured for Windows 10 IoT Core, please refer here.

There are two modes in which you can develop a Windows 10 IoT app, Headed and Headless.

The difference really is that the former supports a UI and the latter is mostly used for background services. For this scenario, we will create a headed app.

Note that since Windows supports the concept of Universal apps, you do not need specialized templates for created Headed or Headless app for IoT devices. The beauty of Universal apps is that the same code can run on any Windows supported device.  The only specialized template available for Windows IoT Core  in Visual Studio is for Background apps. 

Instead of giving a step by step of how the Universal App is created, I provide the key steps that you can use to configure your solution. The entire code for the sample is available on my Github repo here: https://github.com/niksacmsft/IoT.Samples.Universal.EventIngest

  • Create a new Project in Visual Studio using Windows -> Universal -> Blank App (Universal) template.
    • Add the IoT Extension to the project using Reference -> Extensions


  • Add another project to the solution using the Windows -> Universal -> Class Library (Universal Windows) template. We will use this project to add helper and common classes.
    • Add the IoT Extension to this project using Reference -> Extensions -> Windows IoT Extensions for the UWP.
    • Add the following Nuget packages to the project
      • AMQPNetLite: We use this for connecting to EventHub over AMQP
      • Newtonsoft.Json: We use this for serialization and de-serialization of our JSON documents.
  • Build your solution to make sure all things are working OK. When building the package, Nuget will attempt to restore the UWP packages and any other configured packages.
  • Create an Event Hub: For this blog post, I will assume that you know how to create an Event Hub. In case you are new to Event Hubs I have a previous blog entry which talks about Event Hubs, you can refer to it here.
  • Connecting to Event Hub programmatically

    For my sample, I wanted to create a simple library that allows me to connect to Event Hubs on either HTTPS or AMQP protocol. I extended the bits from http://connectthedots.io sample and created a re-usable asynchronous wrapper that I call as ConnectionManager that allows connection to Event Hubs over either of the protocols. I plan to add more protocol to this wrapper in future.

    • For HTTPS it uses a REST API call the Event Hub API and
    • For the AMQP connection it uses AMQPNetLite client library.

    Below is an excerpt of the ConnectionManager.cs class:

<code>
public async Task<bool> SendEvent(Event eventStream)
 {
 eventStream.Timecreated = DateTime.UtcNow.ToString("mm:dd:yyyy hh:mm:ss");
 return await SendMessage(eventStream.ToJson());
 }
 private async Task<bool> SendMessage(string message)
 {
 var protocol = Protocol;
 switch (protocol)
 {
 case Protocol.Amqp:
 return await SendMessageAmqp(message);
 case Protocol.Https:
 return await SendMessageHttps(message);
 default:
 return false;
 }
 }
 
 private async Task<bool> SendMessageHttps(string message)
 {
 if (!this._eventHubConnectionInitialized) return false;
 try
 {
 var content = new HttpStringContent(message, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json");
 var postResult = await _httpClient.PostAsync(_uri, content);
 
 if (postResult.IsSuccessStatusCode)
 {
 Debug.WriteLine("Message Sent: {0}", content);
 }
 else
 {
 Debug.WriteLine("Failed sending message: {0}", postResult.ReasonPhrase);
 }
 return true;
 }
 catch (Exception e)
 {
 Debug.WriteLine("Exception when sending message:" + e.Message);
 return false;
 }
 }
 private async Task<bool> SendMessageAmqp(string message)
 {
 //TODO: figure out if AMQP.NET lite support async method calls
 // construct message
 var messageValue = Encoding.UTF8.GetBytes(message);
 
 // here, AMQP supports 3 types of body, here we use Data.
 var formattedMessage = new Message { BodySection = new Data { Binary = messageValue } };
 _sender.Send(formattedMessage, null, null); // Send the message 
 // _connection.Close(); // close connection
 return true;
 }
</code>
  • Configuring Event Hub connection strings

    Instead of hard coding my event hub and related connection strings, I use a JSON file for persisting this information. The JSON is packaged as part of the IoT.Samples.Universal.EventIngest project and deployed to the device when the application is installed.

    • Create a new folder under Assets folder called Settings
    • Create a new settings.json file under this folder.

    The JSON file itself is fairly simple and looks like this:

<code>
{
 "settings": {
 "servicebusnamespace": "your service bus namespace",
 "eventhubname": "your event hub name",
 "keyname": "the SAS key for sending messages to event hub",
 "keyvalue": "the SAS key value for sending messages to event hub"
 }
}
</code>
  • Configuring the UI for the Universal App

    The UI for my Universal App is very basic, the idea for me was to demonstrate how to connect a device to an Azure backend and generate reports out of it. I did not put a lot of effort in cosmetic and UI aspects.

    I used a FlipView control to show the different departments and leverage the Tapped event to invoke a call my ConnectionManager for sending the selected option to Event Hub.

    Additionally a TextBlock control is used to display success and exceptions.

<code>
private async void flipView_Tapped(object sender, TappedRoutedEventArgs e)
 {
 try
 {
 // try to cast source as content presenter
 var content = e.OriginalSource as ContentPresenter;
 if (content == null) return;
 // Send data to Event Hub
 var eventData = new Event
 {
 Id = "iotboothdevice",
 Timecreated = DateTime.UtcNow.ToString("mm:dd:yyyy hh:mm"),
 Value = content.Content.ToString()
 };
 var result = await _connectionManager.SendEvent(eventData); // send message over event hub
 if (!result) return;
 var message = string.Format("Last Successful Message sent at: {0}", DateTime.UtcNow);
 textBlock.Text = message;
 InitializeFlipView();
 }
 catch (Exception ex)
 {
 textBlock.Text = ex.Message;
 }
 }
</code>

Deploy and Test the app on the PI

Visual Studio 2015
provides seamless integration for deploying, testing and debugging Universal apps on supported devices. To deploy the app on your Pi devices, there are few changes we need to make to our project configuration:

  • Right click and select Properties for the IoT.Samples.Universal.EventIngest project.
  • In the debug tab, select Target device as Remote Machine and enter the IP Address of your Pi device, do not check the Authentication check box.


  • Select ARM as the architecture (this is required for Pi since it is ARM based), the Remote Machine option will be the only option available in the debug now.
  • Now if you run the solution, Visual Studio will attempt to connect to your Pi device and initiate the deployment of the solution. During the deployment it will package the necessary files and dependencies, install any requirement .NET framework version. Finally, it will select the Universal App as the running app on the device. You should see a screen similar to the below:


  • Our app is now running, if you click on any of the FlipView control items, a call will be sent to EventHub to register the selection. The UI will be updated with the last successful message update.


In Part 3 of this blog series, we will leverage Stream Analytics to make sense of the data coming in from the device.


2 thoughts on “Using Win10 Core and Azure IoT Services with Raspberry Pi2 – Part 2

  1. Hi and congratulations for your nice article !

    I’d like to notice you the Azure SB Lite library available on Nuget as package. It’s a library based on AMQP .Net Lite that exposes the same APIs of official Service Bus SDK but it’s able to run on Windows IoT Core so in a UWP app.
    In this way you can write your code to send data to Service Bus (of course Event Hubs included) without changing code between PC and Raspberry Pi 2 … between “standard” windows app and UWP app. You don’t need to know nothing about AMQP protocol (connection, session, link, message and so on) too.

    Here the link to the Nuget package : https://www.nuget.org/packages/AzureSBLite/

    The project is open source and available on GitHub here : https://github.com/ppatierno/azuresblite
    The are some usage examples too : https://github.com/ppatierno/azuresblite-examples

    Paolo.

Leave a comment