Setup Windows IoT core and run your first App

Lab-AzureIoT-wikiazure

Setup Windows IoT core and run your first App

Dave Rendón Follow
1 Star2 Stars3 Stars4 Stars5 Stars

In this article I will show you how to Setup Windows IoT core and run your first App. This article is part of the IoT Virtual Bootcamp –  Predict Temperature using Azure IoT & Raspberry Pi3.

 

Pre-requisites:

  • Required Hardware:
    • Windows 10 PC
    • IoT Hardware kit: https://www.adafruit.com/product/3605 or similar hardware.
    • Access to a WiFi network
  • Required Operating System:
    • Windows 10
  • Other Requirements:
    • Azure Subscription
  • Required Software:
    • Visual Studio: https://aka.ms/vs/15/release/vs_community.exe
    • IoT Core Dashboard: https://go.microsoft.com/fwlink/?LinkID=708576

Let´s Setup Windows IoT core

Windows IoT Core provides you the tools needed to build with Windows 10 IoT Core. The IoT Dashboard is an essential tool for users to get started with Windows 10 IoT Core.

Note: In this article we will use just the Windows IoT Core, not the Enterprise version.

  1. Once you installed Windows 10 IoT Dashboard, run the IoT Dashboard App:

 

IoT-dashboard-2-wikiazure

2. Now you need to click on Setup a New Device, then select the Device Type as Raspberry Pi 2&3, Select the OS Build – Windows 10 IoT Core, in this article I´m using 16299, you could try the latest one. Then insert a SD card into your computer and you should be able to see reflected in the Drive Option. Finally provide a Device name for your IoT Device (IoTBerry in my case) and provide a password – Store this password! .  Click on download and install.

 

IoT-dashboard-3-wikiazure

 

 

3. Iot Dashboard tool will start downloading the selected image and will install it on the SD Card so that we can later use it.

Note: Be sure that the SD card is empty, otherwise IoT Dashboard will warn you about formatting it.

Deployment-image-iot-dashboard-1-wikiazure

This might take a while….

Deployment-image-iot-dashboard-2-wikiazure

 

4. Once the image is applied go back to the IoT Dashboard and click Devices, insert the SD card in Raspberry Pi, Connect a USB Keyboard, a USB mouse and a display to the Raspberry Pi.

install-Windows-IoT-Core-Raspberry-wikiazure

 

Lab-AzureIoT-wikiazure

 

 

ps. Sorry, definitely not a good photographer!

 

5. Power on the Raspberry Pi. It will boot Windows 10 IoT Core automatically. The first time you are booting, this will take a few minutes.

running-Windows-10-IoT-Core-wikiazure

 

Lab-Raspberry-Azure-IoT-wikiazure

 

6. Soon, you should see your PI from the IoT Dashboard, as shown below.  You can view the properties via the Device Portal. Log in as Administrator with the matching password, as shown below:

raspberry-pi3-wikiazure

 

IoT-remote1-wikiazure

7. Now go to Visual Studio, If not already installed, install Visual Studio from: https://aka.ms/vs/15/release/vs_community.exe . select File -> New Project and select Universal App -> Blank App, as shown below, in this case I named the App as IoTBootcamp :

 

App-IoT-wikiazure

 

8. Once created, double click MainPage.xaml on the right, then drag a Text Box to the center page. Change the text to “Hello World” as shown below:

 

modify-text-box-IoT-App-wikiazure
9. With Debug Mode set and x86 platform, click the “Local Machine” debug button and you will see the application start, as shown below:

debug-local-machine-IoT-App-wikiazure

You should see the following output:

Hello-world-IoT-wikiazure

 

10. With Debug Mode still set change the platform to ARM click Device -> Remote Machine. Select the machine auto detected or manually type in the ip address as shown below:

 

Run-IoT-App-Device-wikiazure

 

11. Now go back to the Visual Studio project and replace the following code.

Modify the MainPage.xaml.cs

Note: You can download the project from here.

  • Line 88 defines that we are listening for Property Changes
  • Line 112 parses the desired properties
  • Line 113 says if the interval is not null
  • Lines 117 – 120 stops the timer, applies the new setting, updates the screen and restart the timer
  • Line 123 updates the “reported” property, by calling the method on line 127 – 133
using System;
using Windows.Devices.Gpio;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using System.Text;
using Microsoft.Azure.Devices.Shared;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Blinky
{
    public sealed partial class MainPage : Page
    {
        private const int LED_PIN = 5;
        private GpioPin pin;
        private GpioPinValue pinValue;
        public DispatcherTimer timer;
        private SolidColorBrush redBrush = new SolidColorBrush(Windows.UI.Colors.Red);
        private SolidColorBrush grayBrush = new SolidColorBrush(Windows.UI.Colors.LightGray);
        static string IoTDeviceConnectionString = "HostName=IoTBootcampDR.azure-devices.net;DeviceId=IoTBerryLabs;SharedAccessKey=l/DOgKmpHlzaEzso6DJj0ZLiWDdf0Z5t71YHHHYQwug=";
        static DeviceClient deviceClient;
        Windows.UI.Core.CoreDispatcher dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

        public MainPage()
        {
            InitializeComponent();
            connectToIoTHub();
            receiveMessage();

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(500);
            timer.Tick += Timer_Tick;
            InitGPIO();
            if (pin != null)
            {
                timer.Start();
            }        
        }

        private void InitGPIO()
        {
            var gpio = GpioController.GetDefault();

            // Show an error if there is no GPIO controller
            if (gpio == null)
            {
                pin = null;
                GpioStatus.Text = "There is no GPIO controller on this device.";
                return;
            }

            pin = gpio.OpenPin(LED_PIN);
            pinValue = GpioPinValue.High;
            pin.Write(pinValue);
            pin.SetDriveMode(GpioPinDriveMode.Output);

            GpioStatus.Text = "GPIO pin initialized correctly.";

        }

        private void Timer_Tick(object sender, object e)
        {
            if (pinValue == GpioPinValue.High)
            {
                pinValue = GpioPinValue.Low;
                pin.Write(pinValue);
                LED.Fill = redBrush;
            }
            else
            {
                pinValue = GpioPinValue.High;
                pin.Write(pinValue);
                LED.Fill = grayBrush;
            }
        }

        private async void connectToIoTHub()
            {
                deviceClient = DeviceClient.CreateFromConnectionString(IoTDeviceConnectionString, TransportType.Mqtt);
                await deviceClient.OpenAsync();
                await deviceClient.SetMethodHandlerAsync("changeInterval", changeInterval, null);
                await deviceClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChanged, null);

            IoTSTatus.Text = "Connected to IoT Hub";
        }

        private async Task changeInterval(MethodRequest methodRequest, object userContext)
        {
            if (methodRequest.DataAsJson != null)
            {
                // Because we are in a Task, we have to use a dispatcher to get on the same Thread
                await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, ()=> {
                    timer.Stop();
                    timer.Interval = TimeSpan.FromMilliseconds(Convert.ToDouble(methodRequest.DataAsJson));
                    DelayText.Text = methodRequest.DataAsJson + "ms";
                    timer.Start();
                });
            };

            await UpdateTwin("interval", Convert.ToDouble(methodRequest.DataAsJson.ToString()));
            return null;
        }

        private async Task OnDesiredPropertyChanged(TwinCollection desiredProperties, object userContext)
        {
            dynamic desiredProperty =  JObject.Parse(desiredProperties.ToJson());
            if (desiredProperty.interval != null)
            {
                // Because we are in a Task, we have to use a dispatcher to get on the same Thread
                await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
                    timer.Stop();
                    timer.Interval = TimeSpan.FromMilliseconds(Convert.ToDouble(desiredProperty.interval.Value));
                    DelayText.Text = desiredProperty.interval.Value + "ms";
                    timer.Start();
                });

                await UpdateTwin("interval", Convert.ToDouble(desiredProperty.interval.Value));
            };
        }

        private async Task UpdateTwin(string property, double value)
        {
            TwinCollection reportedProperties = new TwinCollection();
            reportedProperties[property] = value;

            await deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
        }

        private async void receiveMessage()
        {
            while (true)
            {
                try
                {
                     Message IoTMessage = await deviceClient.ReceiveAsync(new TimeSpan(0, 0, 0, 30));
                      if (IoTMessage != null)
                    {
                    string realmessage = Encoding.ASCII.GetString(IoTMessage.GetBytes());
                        if (realmessage.Contains("interval:"))
                        {
                            timer.Stop();
                            DelayText.Text = realmessage.Substring(9) + "ms";
                            timer.Interval = TimeSpan.FromMilliseconds(Convert.ToDouble(realmessage.Substring(9)));
                            await UpdateTwin("interval", Convert.ToDouble(Convert.ToDouble(realmessage.Substring(9))));
                            timer.Start();
                            
                        } else {
                            MyIoTMessage.Text = realmessage;
                        }
                        
                       await deviceClient.CompleteAsync(IoTMessage);
                    }
                }
                catch (Exception er)
                {
                    if (er.Message != "Cannot access a disposed object.\r\nObject name: 'The object has been closed and cannot be reopened.'.")
                    {
                        MyIoTMessage.Text = "receiveMessage Error: " + er.Message.ToString();
                    }
                }
            }
        }
    }
}

12. Run your Application, now you should see the App Running as shown below:

 


 

Until this point you should be able to:

  • Run your app on Windows IoT Core
  • Receive data from your device to your IoT Hub
  • Review the data(Temperature) coming form your device by using serial monitor or in the Azure Portal.

Leave a Reply