Sample Microsoft Azure and PowerApps solution that demonstrates how to use to Azure to intake, process, analyze, and store IoT data then visualize it in a Microsoft PowerApps app.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Assets
clients
images
.gitignore
FleetTracker.zip
PowerAppsTableStorageSettings.swagger.json
README.md
azuredeploy.json

README.md

Using PowerApps to visualize IoT data from Microsoft Azure

In this code sample we show you how to use Azure to intake, process, analyze and store IoT data then visualize it in a Microsoft PowerApps app. Learn how to seamlessly combine the technologies to provide insights into data and take action on it instantly.

When you are done installing this sample you will have a cool PowerApp that looks like this. The PowerApps shows taxis driving around Beijing, China and if they are approching an oil change or are past the point where they need an oil change.

PowerApp

Architecture Overview

The following diagram illustrates the different components in the solution.

Architecture

How It Works

The producer (a .Net console application) simulates sensors attached to taxis. It reads data from .txt files that contain taxi data. Each text file correlates to one taxi. The producer emits data on a regular basis (this is configurable in the appsettings.json file), including the taxi's current location and distance traveled. The producer sends the data to an Azure IoT Hub.

Azure Stream Analytics reads the data from the IoT Hub and copies it to Azure Table Storage.

An Azure Function App reads the data from Azure Table Storage.

The PowerApp invokes a Custom Connector to call the Function App and return the data to the PowerApp where it is rendered. A timer control in the PowerApp invokes the Custom Connector every time the timer reaches it's duration (in the app we have it set to 5 seconds by default).

The PowerApp also makes calls through the Custom Connector to both read and write the last mileage a taxi had an oil change. The last oil change data is stored in a different Table in Azure Table Storage. The Custom Connector invokes Azure Functions to read and write this data. The read operations are used to determine if a taxi is approaching an oil change or an oil change is past due. These values are used to color code the taxis in the list and the pushpins on the map. The write operation allows the maintenance manager to update the mileage when an oil change was made for each taxi.

There are also automated email notifications that are sent when a taxi is approaching an oil change or an oil change is past due. To send these notifications an Azure Function triggers each time data is received by the IoT Hub. The Azure Function evaluates the data to determine if a notification needs to be sent. A Logic App is used to send notifications. It uses an API Connection to Office 365 to send email via Outlook. You can configure the email address where the notifications are sent in the ProcessTaxiDataFromIoTEventHub Azure Function by changing the value for the MaintenanceManager variable.

Connectors

The PowerApp uses the following connectors:

  • Custom Connector named PowerAppsTableStorageSettings - To invoke the Azure Functions.
  • Office365Users - To return metadata about users.

Deployment Instructions

It will take you about 15-20 minutes to deploy and configure this sample.

Create Azure Resources

We have created an ARM template that deploys most of the Azure resources automatically for you. This section describes how to use the ARM template to deploy the Azure resources. The ARM template deploys and configures these components:

  • App Service
  • App Service plan
  • IoT Hub
  • API Connection
  • Logic app
  • Storage account
  • Stream Analytics job
Step-by-step instructions (expand for details)

  1. Click this button to navigate to the Azure portal deployment page.

    Deploy to Azure

  2. Enter a name for the Resource group.

    Template Deployment

  3. Check the I agree to the terms and conditions stated above checkbox.

  4. Click Purchase.

  5. Please DO NOT close the browser window running the Azure resource deployment.

  6. After the Azure resources are deployed successfully, click the Microsoft.Template link to see the output values for FUNCTIONAPPNAME, and IOTHUBENDPOINTPATH.

  7. Copy and paste these values into a text file.

  8. Save the text file.

    You will use the values in subsequent steps.

    Deployment result

  9. In the Notifications, click Go to resource group.

    Go to resource group

  10. In the Overview tab for the resource group, click office365.

    Resource group overview

  11. Under the menu in the Overview tab for the Office365 API Connection, click This connection is not authenticated.

    Office365 overview

  12. Click Authorize to sign in with your account, then click Save.

    Office365 API Authorization

  13. Return to the resource group, and click IoTHub.

    IoT Hub

  14. Click the IoT devices tab.

    IoT Hub Devices

  15. Click Add.

    Add device

  16. Fill the field Device Id, then click Save.

    In this case, the Device Id is MyDotnetDevice.

    Add device

  17. Click the device you just created, then copy the Connection string (primary key) in the device details page, and save it as IOT_HUB_CONNECTION_STRING in your text file.

    Device connection string

Azure Function Configuration

After the Azure resources are deployed you can deploy the Function App. This section describes how to do that.

Step-by-step instructions (expand for details)

  1. Download and extract or Clone the repo from https://github.com/OGcanviz/IoTPowerApp

  2. Open the file Assets/ProcessTaxiDataFromIoTEventHub/function.json

  3. Update the bindings/path value with the IOTHUBENDPOINTPATH value you saved in the text file.

     {
       "bindings": [
         {
           "type": "eventHubTrigger",
           "name": "myEventHubMessage",
           "connection": "TaxiDataIoTHub_events_IOTHUB",
           "path": "taxidataiothub",
           "consumerGroup": "ProcessTaxiDataFromIoTEventHub",
           "cardinality": "many",
           "direction": "in"
         }
       ],
       "disabled": false
     }
  4. In a web browser, go to https://<function_app_name>.scm.azurewebsites.net/DebugConsole

    Note: Replace the <function_app_name> placeholder with the FUNCTIONAPPNAME value you saved in the text file.

  5. Click site, then click wwwroot to go to the D:\home\site\wwwroot directory.

  6. Configure the email address where the notifications are sent in the ProcessTaxiDataFromIoTEventHub Azure Function by changing the value for the MaintenanceManager variable in the ProcessTaxiDataFromIoTEventHub/run.csx file before you upload the files. You can also change this setting after the files are uploaded by editing it in the Azure Portal.

  7. Upload the GetLastOilChange, IoTTableStorageFunction, ProcessTaxiDataFromIoTEventHub and SetLastOilChange folders by dragging and dropping them from your local file system to the wwwroot folder at the top half of the page.

    Note: You may have to manually create the GetLastOilChange, IoTTableStorageFunction, ProcessTaxiDataFromIoTEventHub and SetLastOilChange folders in some browsers and then drag & drop the files into the new folder.

    App Service Folder

    After you upload the files, you will see them appear in the file list:

    Copy TableStorageFunction folder to wwwroot folder

Validate the Azure resources are successfully deployed and configured

Now you will run the console application to send taxi data to the Azure IoT Event Hub. This section describes how to do it.

Step-by-step instructions (expand for details)

Note: If you wish to run the producer from Visual Studio, please see the instructions in the ConsoleAppsReadme.md.

Use the command-line producer for macOS, Linux, or Windows to produce messages into the stream.

  1. First, download the producer for macOS (producer-osx-x64.zip), Linux (producer-linux-x64.zip) and Windows (producer-win10-x64.zip).

  2. Unzip the file.

  3. Open the appsettings.json file.

  4. Update the connectionString value with the IOT_HUB_CONNECTION_STRING value you saved in the text file.

     {
       "clientFiles": "taxiData/1131.txt",
       "speed": 1,
       "IoT Hub": {
         "connectionString": "IOT_HUB_CONNECTION_STRING"
       }
     }

    Note: If you wish to simulate multiple taxis, include multiple source data files in the clientFiles value, like this:

     {
       "clientFiles": "taxiData/1131.txt,taxiData/1277.txt,taxiData/2560.txt,taxiData/2669.txt,taxiData/3015.txt,taxiData/3557.txt,taxiData/3579.txt,taxiData/3781.txt,taxiData/4798.txt,taxiData/5075.txt,taxiData/5099.txt,taxiData/5860.txt,taxiData/6275.txt",
       "speed": 1,
       "IoT Hub": {
         "connectionString": "IOT_HUB_CONNECTION_STRING"
       }
     }

    Note: If you wish to speed up the rate the data is sent to Azure, increase the speed value. This will make the taxis appear to drive around faster and log more miles quicker.

     {
       "clientFiles": "taxiData/1131.txt,taxiData/1277.txt,taxiData/2560.txt,taxiData/2669.txt,taxiData/3015.txt,taxiData/3557.txt,taxiData/3579.txt,taxiData/3781.txt,taxiData/4798.txt,taxiData/5075.txt,taxiData/5099.txt,taxiData/5860.txt,taxiData/6275.txt",
       "speed": 6,
       "IoT Hub": {
         "connectionString": "IOT_HUB_CONNECTION_STRING"
       }
     }

    Note: If you wish to add a initial mileage to each taxi, add a baseMileages setting for each taxi.

     {
       "clientFiles": "taxiData/1131.txt,taxiData/1277.txt,taxiData/2560.txt,taxiData/2669.txt,taxiData/3015.txt,taxiData/3557.txt,taxiData/3579.txt,taxiData/3781.txt,taxiData/4798.txt,taxiData/5075.txt,taxiData/5099.txt,taxiData/5860.txt,taxiData/6275.txt",
       "speed": 6,
       "IoT Hub": {
         "connectionString": "IOT_HUB_CONNECTION_STRING"
       },
       "baseMileages": {
         "1131": "4000",
         "1277": "2000",
         "2560": "500",
         "2669": "0",
         "3015": "3000",
         "3557": "0",
         "3579": "0",
         "3781": "0",
         "4798": "0",
         "5075": "1800",
         "5099": "0",
         "5860": "0",
         "6275": "0"
       }
     }
  5. Save the file.

  6. Open a Command Prompt on your local machine, then go to the folder that hosts the extracted taxi producer files and run the taxi data producer to start emitting sensor data to the Azure.

    In Mac & Linux environments, run the following command:

    ./producer

    In a Windows environment, run the following command in the CMD console:

    producer.exe

    Each time the producer sends a message to the stream it prints a period on the screen, like this:

    ./producer or producer.exe
    ...................................................................
    ...................
  7. Finally, use the Microsoft Azure Storage Explorer to view the data and verify it made its way to the Azure Table Storage table.

    For example:

    Azure Table Storage

    When you see data appearing in the Azure Storage Table you can move on to the next steps.

PowerApps Deployment

Import Custom Connector

This section describes how to deploy the custom connector named PowerAppsTableStorageSettings. This is the custom connector that invokes the Azure Functions.

Step-by-step instructions (expand for details)

  1. In a web browser, go to https://web.powerapps.com and login with your Office 365 account.

  2. Click the setting button on the navbar, then click Custom connectors to go to the custom connectors list.

    Custom Connectors

  3. Click the Create custom connector button, then click Import an OpenAPI file.

    Import Custom Connector

  4. Enter the Custom connector title, select Upload an OpenAPI file, then click Continue.

    Note: Use the value and file linked in the table below to complete this step.

    Fields Value
    Custom connector title PowerAppsTableStorageSettings
    Upload an OpenAPI file PowerAppsTableStorageSettings.swagger.json

    Create Custom Connector

  5. In the General section, replace the Function App name in the Host field. <function_app_name>.azurewebsites.net

    Note: Replace the <function_app_name> placeholder with the FUNCTIONAPPNAME value you saved in the text file.

    Change Host Name

  6. Save the Custom Connector.

    After you save it, you will see it appear in the Custom Connector list.

  7. Create a connection to the Custom Connector you just created by clicking the add mark in Custom Connector item.

    Create Custom Connection

Import the PowerApp

Now you will import the PowerApp to your PowerApps environment and configure it to use the custom connector. These steps describe how to do it. Step-by-step instructions (expand for details)

  1. In a web browser, go to https://web.powerapps.com and login with your Office 365 account.

  2. Click Apps in the left menu, then click Import package (preview).

    Import Package

  3. Click Upload in the following page, then select the file FleetTracker.zip.

    Upload Package

  4. After the upload is complete, you will see this page.

    Import Package Configuration

  5. Click the settings button for PowerAppsTableStorageSettings, select the custom connector you just created, then click Save.

    Connection Selection

  6. Click Import.

  7. After the import process completes, the app is published as well.

Get a Bing Map Key

This section describes how to create a Bing Maps API Key. The Bing Maps API Key is required to display maps in the PowerApp.

Step-by-step instructions (expand for details)

1. Log into the Azure Management Portal with an account that has permissions to deploy new Azure resources.

  1. Click Create a resource, then enter Bing Maps API for Enterprise in search box and press Enter.

    Search for Bing Maps API for Enterprise

  2. Fill the field name and select the resource group you just created, then set the Price Tier to Public Website Transactions Level 1.

    Note: In this case, the name is BingMapsAPI, you can use any name you like.

    Create Bing Map

  3. Click Legal terms, then click Create.

    Bing Maps Legal Terms

  4. Click Create.

  5. After the creation process is complete, open the resource group you selected and click the BingMapsAPI item.

    Select Bing Maps

  6. Click the Key icon, like this.

    Select Bing Maps

  7. You can copy the Master Key or Query Key as Bing Map API Key. Save it to a text file, you will need it in subsequent steps.

    Select Bing Maps

Run the PowerApp

Now the fun part, run the PowerApp!

Step-by-step instructions (expand for details)

  1. In a web browser, go to https://web.powerapps.com and login with your Office 365 account.

  2. Click Apps in the left menu, then click the App you just created.

    Run app

  3. Click the Show timer toggle in the title bar, then click Play.

    Start

  4. You can go to the settings page by clicking the gear icon in the header.

    Settings

  5. Enter your Bing Map API Key and click Select Driver to select a user for each taxi, then click Save.

    Note: You need to set Bing Map API Key every time you open the app. If you want your Bing Map API Key to persist you can modify the code in the OnStart method in the TaxiInfo screen to set a default API Key. Like this:

    Set(BingMapApiKey,"YOUR BING MAP API KEY");

    Note: You can also use the settings screen to set the last oil change mileage values for each taxi.

    Settings

  6. Now the app looks like this.

    Start

Follow Up

For more awesome PowerApps tips, tricks, and samples, check out our blogs.

Todd Baginski's Blog

Canviz Blog

Contributors

Roles Author(s)
Project Lead / Architect / Development Todd Baginski (Microsoft MVP, Canviz) @tbag
Development Hubert Sui (Canviz) @hubertsui
Development Manfred Wittenbols (Canviz)
Development Alex Belikov (Canviz)
Testing Melody She (Canviz) @melodyshe
Design Justin So (Canviz)
Casey Burke (Microsoft)

Version history

Version Date Comments
1.0 August 3, 2018 Initial release

Disclaimer

THIS CODE IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.