Qt – UWP – Raspberry Pi

Capture

Ok, the title sounds like technology bingo – three apparently unrelated technologies. Here is how they fit together …

I was looking for an app framework for a simple app I wanted to write for my Raspberry Pi 3. One of my requirements for the app was that it needs to run with Raspbian (Linux) as well as with Windows IoT Core installed on my Pi. The latter exclusively runs UWP applications, but UWP apps typically can’t run on Raspbian. So what to do here?

Qt support for UWP

A little know fact about the Qt application framework is that it is compliant with the UWP app model and API specifications. And I mean UWP proper here, not Desktop Bridge for PCs. So this means you can compile and package your Qt app as a UWP app package that can then run on any Windows 10 device – PC, Xbox, HoloLens, Surface Hub and Window IoT Core!

Even if you are building only for desktop PC, this can be interesting to consider if you want to take advantage of new Windows 10 UWP APIs or modern app deployment incl. Microsoft Store distribution. Last, and certainly not least, running your Qt app as UWP will let you take advantage of the AppContainer – the unsung hero of the Windows app platform. The AppContainer ensures that the app process won’t have any undesired impact on system stability or security by keeping it in a sandbox that is defined by UWP’s capability model. In this model, for example, a calculator app only gets the capabilities it needs. It won’t be able to use the internet, read arbitrary files from the disk or mess with the system’s registry. Even if the app has a bug and the process gets hacked it won’t be able to act outside of its sandbox.

In short, Qt is a great cross-platform option worth considering when you want to get the most out of Windows 10 and need to run the same code on Windows 7, Linux, Mac, Android or iOS.

Creating a Qt UWP sample app

First step is to install Qt on our development box from https://www.qt.io/download. Then launch the Qt Creator IDE to create your first Qt application – or select one of the examples that come with the tools.

createnew

Select an application type, such as “Qt Widget Application” and give it a name. Next comes the “Kit Selection” screen:

kitselection

Let’s select one of the classic desktop kits and one of UWP kits (make sure the processor architecture works for your dev machine). Also be sure you select the UWP-ARMv7-MSVC2017 kit as we will need it for the Raspberry Pi. Then finish the project creation by accepting all the defaults. Now you can hit F5 to compile, launch and debug your project. Use the Selector control on the left pane to switch between classic desktop and UWP flavors to test your app code in both environments:

switchkit

Side-track: Distributing via Microsoft Store

The UWP Release build output is in the right format for distribution via the Microsoft Store. There are a couple of steps/best practices to follow when submitting the application the Store. I’ll save those details for a future blog post as this is not required for getting the Qt app onto the Raspberry Pi, but to make sure this is indeed working seamlessly with the Qt framework I have taken one of the examples (the Qml Oscilloscope one) and actually put it in the Store – just for testing purposes. I have set it to be not searchable in the Store, but you can get to it and install the sample via this direct link: https://www.microsoft.com/store/apps/9NVKHDDVB44D

 

Deploying the Qt sample app to Raspberry Pi

The Qt Creator IDE doesn’t have the capability to produce UWP distribution packages (unlike Visual Studio), so you will have to create those manually before distributing the app to your devices. Here are the steps to get your Qt app deployed and run on your Pi (or other devices running Windows IoT Core for that matter):

1. Select “UWP-ARMv7-MSVC2017” Kit and build as “Release”

Configure kit/build per below and then select Build->Rebuild All menu.

switchtoarm

2. Create the .appx package file

In a developer command prompt, go to the build output folder. It should be called something like “build-FirstQtApp-Qt_5_11_2_for_UWP_ARMv7_MSVC_2017-Release”. Then run this command to create an .appx package named “qtapp.appx” from the contents of the “release” directory

makeappx pack -p qtapp.appx -d .\release

3. Sign the .appx package

Windows 10 devices only install .appx packages that are signed with a trusted certificate. So we will need to sign our package before we can run it. If you don’t have a certificate that is trusted on your devices (e.g. from Verisign etc.) you can create a test certificate and install it on your device – for testing purposes. The tools you need to create the test certificate and sign the .appx come with the Windows 10 SDK (which comes with Visual Studio 2017). Make sure <pn> matches what is specified as publisher name in the appxmanifest.xml file. Also note that qtapp.appx is the name you selected in the previous step for your package. For the names of qt.pvk, qt.pfx, qt.cer you can select whatever you want. For full details on these steps refer to the official documentation.

MakeCert.exe -r -h 0 -n "CN=<pn>" -eku 1.3.6.1.5.5.7.3.3 -pe -sv qt.pvk qt.cer
pvk2pfx.exe -pvk qt.pvk -spc qt.cer -pfx qt.pfx
signtool.exe sign -f qt.pfx -fd SHA256 -v .\qtapp.appx

4. Use Windows Device Portal to install the app on the Pi

With the Windows Device Portal application deployment and management is very easy. To get to the portal, get the IP address of your Pi and navigate to port 8080 (in my example 192.168.1.220:8080):

wdp

In the portal now go to Apps->Apps Manager to deploy your app with these steps:

  1. If you are using a test certificate, install it on your test device using the “Install Certificate” button. Just browse to the qt.cer file you created earlier and hit “Install”
  2. Depending on your app, you might have to select dependent framework packages. Those are listed in your appxmanifest.xml file in the build output. For that check the box and then get the required packages from “%ProgramFiles(x86)%\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\”
  3. Browse to the qtapp.appx file you have created in an earlier step and hit “Install”

Now your app should be installed and ready to run. You can launch and manage its lifetime from the Apps Manager here in the portal. Or you can launch it manually via the standard Windows IoT Core Shell. For my experiment I picked the Qml Oscilloscope example:

winiotcore

appslist

apprunning

Now you have your Qt app running on Windows IoT Core. The exact same app code can be compiled for and deployed to Raspbian (Linux) as well. The steps for this are well documented so I won’t go into it here. I recommend using this guide for Qt on Raspbian: https://wiki.qt.io/Raspberry_Pi_Beginners_Guide

 

Capture

Advertisements

Azure IoT with UWP

blogTitleRecently I moved to a new role within Microsoft and I am now working on the developer experience for Azure IoT. Going forward I will be shifting my blog activities to be more focused on IoT and Cloud development topics, across the diverse spectrum of technologies that is IoT today. To begin this transition I will start with a couple of introductory posts at the intersection of my previous and my current role: using the Azure IoT SDKs from UWP applications. In fact, if you are like me coming from a UWP/.NET background this is a great path to ramp up on Azure SDKs and to working with the cloud.

The Azure IoT SDKs for both the device and service side support a diverse set of programming languages and operating systems, including UWP on Windows 10. If you are using Windows IoT Core on your devices (“things”) then UWP is your choice for device app development. Also, if you are building a backend application for Windows 10 that connects to Azure IoT services, UWP can be the right tool for the task. In this first post I will focus on building a simple device application.

Building a Rating “Thing”

Simple goal for this first post: Using my Raspberry Pi 3, loaded with Windows IoT Core 17763 (aka 1809 update) I want to build a “thing” that lets customers rate their experience and sends that data to the cloud. You may have seen screens like this in airport bathrooms:

ratingux

What do I need?

  • Visual Studio 2017 with the latest updates
  • Azure subscription (free trial subscription will be sufficient for this example)
  • Raspberry Pi 3 (or any other device running Windows IoT Core)

If you don’t have an IoT device yet, you can still play along and use your PC as (simulated) IoT device. This is where the “universal” part of UWP comes in very handy because you will be able to run the same UWP app on both your PC and the device.

Preparation Steps

Azure Portal

Log into the Azure Portal and create an IoT Hub resource (choose the “Free Tier”)

iothub

Once the resource has been created, go to it and select “IoT Devices” from the left pane and click “Add”

adddevices

Now pick a name for your device and click “Save”

createDevice

Last step is to select the newly created device in the list and copy its connection string from the device details. Store this in notepad or somewhere so can get to it in a later step easily.

connstring

If you want to test with more than one device, please repeat the above steps for each device. I’d recommend you create at least two devices: one for your Raspberry Pi and one for your PC, so can test from both and observe the data flowing into Azure from more than one device.

Device

If you are using your PC as (simulated) device then there is nothing else to do here. For your Raspberry Pi follow the official steps from docs.microsoft.com to set up the latest Windows IoT Core build (at the time of this writing it was build 17763). Setup, configuration and maintenance of your Windows IoT Core device is a breeze using the Windows 10 IoT Dashboard and the Windows Device Portal.

Visual Studio 2017

Just make sure you have the latest updates and the Universal Windows Platform workload selected as part of your setup:

uwp

Now there are three options for you to get the device app running and connected to Azure:

1. Install the app from the Store and start running it from your PC (as simulated IoT  device)

You can find the pre-built sample app in the Microsoft Store at the below link. Install and launch it from there: https://www.microsoft.com/store/apps/9NGS2T2X166N

enterstring

The device app needs to know what the respective device’s connection string so can successfully connect to the Azure IoT Hub. So copy the string you had saved in the earlier step and paste it here. Click OK and once the connection is established the controls will be enabled and you can start submitting your ratings.

For an initial quick verification that the messages are arriving in your IoT Hub, navigate to the Azure Portal a go to your IoTHub resource. In the overview section, click on the “Device to cloud messages” chart and verify that your messages are arriving as expected. This view of Azure Monitor data may take a minute or two to get updated:

azmonitor

 

2. Download the source from GitHub, build and run it on your PC (as simulated IoT device)

To learn about the code, step through it in the debugger, make modifications etc. you can get the VS solution from here:

https://github.com/wickste/RatingThing

Open the RatingThing.sln solution in Visual Studio make sure you select x86 or x64 as target architecture and hit F5 to run with the debugger. Again you will need to enter your device’s connection string.

 

3. Deploy the app to your Raspberry Pi and connect it to Azure

Now the interesting way to run it of course is on your actual device (e.g. Raspberry Pi). For that you want to put the respective device connection string in the code (at the top of MainPage.xaml.cs. Note that in a production scenario you would not be doing it this way. Instead you would be using the Azure IoT Hub Device Provisioning Service that enables secure device provisioning at scale.

Next we set up VS for remote deployment and debugging for your Raspberry Pi. Select “ARM” as your architecture and “Remote Machine” as your target – then go into the Debug settings of your project properties to select the specific device you want to deploy to:

remotedebug

Now you can hit F5 to deploy and debug, just like you normally do for your desktop applications (just note that everything will be a bit slower …). So here we have it – our UWP app running on the Pi, connected to our Azure IoT Hub service:

 

Step-by-Step Code Review (full source here)

We start with the empty UWP app template and add a Nuget package for the Azure IoT Device Client SDK:

nuget

The XAML for our UI is extremely simply, thanks to the built-in RatingControl. Just stack the RatingControl on top of a TextBlock and a Button, and then wrap it all in a Viewbox for proper sizing on different display sizes:

<Viewbox Margin="24">
    <StackPanel>
        <RatingControl x:Name="ratingControl" IsEnabled="False"/>
        <TextBlock Text="Rate Your Experience"/>
        <Button x:Name="btnSubmit" Margin="12" IsEnabled="False"
                Content="Submit" Click="btnSubmit_Click"
                HorizontalAlignment="Center"/>
    </StackPanel>
</Viewbox>

Now we need to write the code to connect to our Azure IoT Hub, assuming we have obtained our device connection string (either from the dialog, or hard-coded in the source). Once our connection request has been processed we update the UI controls according to the connection status:

private void ConnectToAzure()
{
         
  iotHubClient = DeviceClient.CreateFromConnectionString(connectionString,
                                                         TransportType.Mqtt);
  iotHubClient.SetConnectionStatusChangesHandler(
    new ConnectionStatusChangesHandler(this.StatusChangesHandler));
  iotHubClient.OpenAsync();
}

private async void StatusChangesHandler(ConnectionStatus status,
                                        ConnectionStatusChangeReason reason)
{
  await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
  {  
    if (status == ConnectionStatus.Connected)
    {
      ratingControl.IsEnabled = true;
      btnSubmit.IsEnabled = true;
    }
    else
    {
      ratingControl.IsEnabled = false;
      btnSubmit.IsEnabled = false;
    }
  });
}

Last step to do is send the data whenever a customer provides their rating. In addition to the rating value, we also want to pass along some system health data to our backend. In this simple example I am adding the current memory usage to the telemetry message so we can build insights on the backend about our app’s health over time (subject of a future post):

private async void btnSubmit_Click(object sender, RoutedEventArgs e)
{
  ulong kiloBytes = MemoryManager.AppMemoryUsage / 1024;
  int rating = (int)ratingControl.Value;

  Message message = new Message();
  message.Properties.Add("rating", rating.ToString());
  message.Properties.Add("app-memory-usage", kiloBytes.ToString());

  await iotHubClient.SendEventAsync(message);
  ratingControl.ClearValue(RatingControl.ValueProperty);
}

That’s it. Pretty easy to get to this point thanks to Visual Studio, .NET & C# and the Universal Windows Platform. In the upcoming posts I will extend the solution on the cloud side and show several options for processing the data from our Rating Thing in Azure and taking action on the insights gained from our devices.

ablogTitle