top of page

Azure IoT Intelligence for Supply Chain - Downtime scenario

Updated: Jul 28, 2021

IoT devices are typically made up of a circuit board with sensors attached that use WiFi to connect to the internet and to to send data collected by sensors. E.g.:

  • A pressure sensor on a remote oil pump.

  • Temperature and humidity sensors in an air-conditioning unit.

  • Presence sensors in a room.

Here, we are taking a closer look at a Equipment downtime scenario with Azure IoT devices – The downtime scenario compares measured uptime to user-defined parameters. Dynamics 365 for Supply Chain Management notifies you when an outage threshold is exceeded, so that you can take actions such as rescheduling a production work order and/or creating a maintenance work order.


Setup and Configuration

1.Set up Azure resources for IoT Intelligence

First we create the Azure resources for the IoT hub, the Redis cache, and the key vault that can later be accessed by Microsoft Dynamics 365 Supply Chain Management.

  1. Verify that the Microsoft Dynamics ERP Microservices first-party app ID is installed in your tenant:

  2. Sign in to Azure portal via https://portal.azure.com and navigate to Azure Active Directory/Enterprise applications.

  3. Select Microsoft applications in the Application type field and enter Microsoft Dynamics ERP Microservices in the search field.

  4. Verify that Microsoft Dynamics ERP Microservices is in the list. (app ID is 0cdb527f-a8d1-4bf8-9436-b352c68682b2)

If the application is not installed under your tenant, please follow the below steps:

  1. In the Azure portal, on the toolbar, select the button to open Azure Cloud Shell.

  2. Run the command Install-Module AzureAD. Enter Y to install the module.

  3. Run the command Get-InstalledModule -Name "AzureAD" to verify that the module is installed.

  4. Run the command Connect-AzureAD -Confirm to run the authentication.

  5. Run the command New-AzureADServicePrincipal -AppId 0cdb527f-a8d1-4bf8-9436-b352c68682b2.

  6. Repeat step a-c above to validate app is installed under your tenant now.

2. Create a key vault resource

  1. In the Azure portal, create or navigate to a resource group and select Add.

  2. On the New page, enter Key vault n the search field and confirm with Create.

  3. On the Create key vault page, enter a name in the Key vault name field (Here: e.g. kv-d365-iot-westus) and select Review + create.

3. Create an IoT hub resource

  1. Create or navigate to a resource group and select Add.

  2. On the New page, enter Iot Hub in the search field and select Create.

  3. Enter a name in the IoT hub name field (Here: e.g. d365-scm-iothub) and select Review + create.

4. Create a Redis cache resource

  1. Create or navigate to a resource group and select Add.

  2. On the New page, enter Azure Cache for Redis in the search field and select Create.

  3. Enter a name in the DNS name field and select Create.

5. Configure the Azure resources

All required Azure resources are created now, we still need to configure the resources.


6. Configure the IoT hub

  1. Under resources, select the IoT hub resource and select Built-in endpoints on the left hand side.

  2. Under Consumer groups, add the following consumer groups. These consumer groups correspond to the out-of-box scenarios for IoT Intelligence in D365FO for SCM.

  • microsoft.dynamics.iotintelligence-1

  • microsoft.dynamics.iotintelligence-2

  • microsoft.dynamics.iotintelligence-3

7. Configure the key vault

  1. Under resources, select the key vault resource and select Access policies on the left hand side.

  2. Select Add an access policy and on the Add access policy page select Get and List in the Secret permissions field.

  3. Click in the Select principal and search for and select Microsoft Dynamics ERP Microservices in the Principal dialog box. Confirm with Add and Save. The app now has access to the secrets in the key vault.

8. Save the IoT hub connection string secret

  1. Under resources, select the IoT hub resource and select Built-in endpoints on the left hand side. Lastly, copy the value in the Event Hub-compatible endpoint field.

  2. Navigate to the key vault resource and on the left hand side select Secrets and Generate/Import.

  3. Enter a name in the Name field and paste the endpoint value that you copied earlier in 1. in the Value field. Confirm with Create.

9. Save the Redis cache connection string secret

  1. Select the Redis cache resource under resources and select Access keys and copy the value in the Primary connection string field.

  2. Now, navigate to the key vault resource and select Secrets on the left hand side.

  3. Select Generate/Import and enter a name in the Name field. Lastly, paste the connection string that you copied earlier in 1. in the value field and confirm with Create.

10 Set up schema formats for IoT Hub messages

The below explains how message schemas are to be designed for usage in IoT Intelligence.

Message requirements

  • Message schemas need be in JavaScript Object Notation (JSON) format.

  • A UNIX timestamp property (value is expressed in milliseconds (ms)) must be present in the Microsoft Azure IoT Hub message at all times.

  • Only if all properties are existent for that specific scneario (Here: Downtime) the message is tracked. E.g. For example, if id, timestamp, and value properties are defined, the following message is monitored.

  • JSONCopy { "id": "IoTInt.Machine1225.PartOut", "timestamp": 1576016821614, "value": True }

  • However, the below message wouldn't be monitored, because the value property is missing.

  • JSONCopy { "id": "IoTInt.Machine1225.PartOut", "timestamp": 1576016821614, } .

  • You can define and use multiple types of message schemas.

  • You can take advantage of id-value pair schemas to ensure your message schema is the consistent across all the scenarios.

  • E.g. downtime scenario:

  • { "id": "IoTInt.Machine1225.PartOut", "timestamp": 1576016821614, "value": True }

  • E.g. product quality:

  • { "id": "IoTInt.Machine1225.Temperature", "timestamp": 1576016821614, "value": 105 }

  • Both messages contain id and value properties - The id values can be mapped in the Signal Data Values table during scenario setup. E.g. Equipment downtime scenario will be mapped to the IoTInt.Machine1225.PartOut and the Product quality scenario will be mapped to the IoTInt.Machine1225.Temperature value.

11. Install the IoT Intelligence add-in in LCS

In order to use IoT Intelligence for D365FO SCM, we need to install the IoT Intelligence add-in in Microsoft Dynamics Lifecycle Services (LCS).


12. Set up the LCS environment

  1. Open LCS, and navigate to your Microsoft Dynamics 365 Supply Chain Management environment. Under the Environment add-ins section, select Install a new add-in to show the list of add-ins that have been enabled for the environment.

  2. In the Select an add-in to install dialog box, select IoT Intelligence. Then, provide the details of your IoT hub and Redis cache. (find required values in the key vault that we created prior):

  • Tenant ID – In the Azure portal, go to the key vault, and then, in the left navigation pane, select Overview, and copy the Directory ID value. Paste that value in the Setup add-in dialog box.

  • IoT Event Hub-compatible endpoint Key Vault URI Go to the key vault, and then, in the left navigation pane, select Overview, and copy the DNS name value. Paste that value in the Setup add-in dialog box.

  • IoT Event Hub-compatible endpoint secret name – Go to the key vault, and then, in the left navigation pane, select Secrets, and copy the name of the secret where the event hub connection string for the IoT hub is stored. Paste that value in the Setup add-in dialog box.

  • Redis cache key vault URI – Go to the key vault, and then, in the left navigation pane, select Overview, and copy the DNS name value. Paste that value in the Setup add-in dialog box.

  • Redis cache endpoint secret name – Go to the key vault, and then, in the left navigation pane, select Secrets, and copy the name of the secret where the connection string for the Redis cache is stored. Paste that value in the Setup add-in dialog box.

` 3. Select the check box to accept the terms and conditions and select Install.


13. Configure metrics

LCS is also set up now. As a next step, we set up the scenarios in D365FO for SCM (here: downtime scenario). First we need to set up the metrics since we want to view the time series charts of IoT messages in Microsoft Dynamics 365 Supply Chain Management.

  1. Copy the connection string for the Redis cache:

  2. In the Azure portal, navigate to the Redis cache and Settings > Access keys.

  3. Copy the value in the Primary connection string field.

  4. In D365FO for Supply Chain Management, navigate now to Production control > Setup > IoT Intelligence > Scenario parameters. On the Scenario parameters page, on the Time series tab, in the Redis metric store connection string field, paste the connection string that you copied earlier.

  5. Now navigate to to Production control > Inquiries and reports > IoT Intelligence > Metric keys.

  6. On the Metric keys page, select Update.

  7. In the Update metric keys dialog box, notice that Run in the background is selected in the field. Select OK.

All the metric keys in the Redis cache are retrieved and added to the Metric keys list. Please, note that metric values won't appear until you actually enable the scenarios (see step 15.)


14. Configure the Resource Status time series

  1. In Supply Chain Management, navigate to Production control > Manufacturing execution > Resource Status and on the Resource status page, select Configure.

  2. In the Configure dialog box, in the Resource list, select an item to monitor and select the Edit button for Time series 1.

  3. In the Select time series dialog box, select a metric in the grid. (You can also use the Update metric keys link to update the metric keys from this dialog box.)

  4. Confirm with OK to return to the Configure dialog box.

  5. Enter a display name.

  6. In the Show data from field, select a time frame and confirm with OK. The chart is now shown.

15. Scenario setup for IoT Intelligence (Here: Downtime scenario)

The Equipment downtime scenario maps a PartOut signal to a machine alert threshold. The machine is monitored only when it's selected for the scenario and when is set to Running in Supply Chain Management. If the time since a PartOut signal was last received from the machine exceeds the alert threshold, a Machine down notification is triggered. If the machine is still running, a Machine up notification is triggered when the next PartOut signal is received. If a machine stays down for 30 minutes, a new Machine down notification is triggered.

The Equipment downtime scenario has the following dependencies:

  • An alert can be triggered only if a production order is running on a mapped machine.

  • A signal that represents a mapped machine's PartOut signal must be sent to the IoT hub, and a unique property name must be included.

  • A UNIX timestamp property, where the value is expressed in milliseconds (ms), must be present in the Azure IoT Hub message.

To configure the scenario, follow these steps.

  1. Sign in to Supply Chain Management and enable the IoT Intelligence feature flag. (under feature management) make sure you have step 13 and 14 above completed.

  2. Navigate to Production control > Setup > IoT Intelligence > Scenario management.

  3. On the Equipment downtime tile, select Configure to open the configuration wizard. The first page in the wizard is the Equipment sensor schema definition page. On this page, your goal is to set up the schema in Supply Chain Management so that it matches the JavaScript Object Notation (JSON) format of the IoT Hub messages. In this example, the message payload contains a batch of messages that has the following format.

  • JSONCopy

  • { "timestamp": 1576016821614, "payload": [ { "id": "IoTInt.Machine1225.PartOut", "timestamp": 1576016821614, "value": True }, { "id": "IoTInt.Machine1226.PartOut", "timestamp": 1576016991616, "value": True } ] }

  1. Add a row to the table, and set the following values:

  2. Set the Schema name field to ID.

  3. Set the Schema path field to /payload[*]/id.

  4. Set the Description field to Message ID.

  5. Add another row to the table, and set the following values:

  6. Set the Schema name field to Timestamp.

  7. Set the Schema path field to /payload[*]/timestamp.

  8. Set the Description field to Message timestamp.

  9. Add another row to the table, and set the following values:

  10. Set the Schema name field to Value.

  11. Set the Schema path field to /payload[*]/value.

  12. Set the Description field to Message value..

  13. Select Next to go to the Equipment sensor schema map page.

  14. In the row for Equipment resource ID, in the Schema name field, select ID.

  15. In the row for UTC time, in the Schema name field, select Timestamp.

  16. In the row for Part produced signal, in the Schema name field, select Value.

  17. Select Next to go to the Equipment resource ID configuration page.

  18. Follow these steps to map the values in the IoT Hub message to the Supply Chain Management resources:

  19. In the Signal Data Values table, add a new row. In the Value field, enter IoTInt.Machine1225.PartOut. This value comes from the JSON id property in the IoT Hub message.

  20. Select Save.

  21. In the Business Record Mapping table, select New. A default value for the Business record type field is automatically filled in, and you don't have to change it.

  22. In the Business record field, select the Supply Chain Management machine resource that the signal value is being sent from.

  23. Select Save.

  24. Repeat these steps to add a new business record mapping for Machine1226. You can map multiple signal data values to a single record in Supply Chain Management.

  25. Use the Selected column to select the machines that you want to process. You don't have to define all signal values, and you don't have to select all machines.

  26. Select Next to go to the Part produced signal configuration page.

  27. In the Signal Data Values table, add a row, and set the Value field to True. This value comes from the JSON value property in the IoT Hub message. You can add as many values as you require for your scenario.

  28. Select Save.

  29. Select Next to go to the Equipment downtime threshold page. The machines that are listed are the machines that were previously mapped to signal values. On this page, you will define a threshold to determine whether a machine is down. For example, if you set the threshold to 10, Supply Chain Management will generate a notification if no PartOut signal is received from a machine for 10 minutes.

  30. Select Next to go to the Enable scenario page. Set the option to enable the scenario.

  31. Select Finish.

The scenario setup is now completed. IoT Intelligence will automatically start to process the IoT Hub messages.


16. Connect Raspberry pi project to Azure IoT hub

See below my raspberry pi project for the sensor that will send the collected IoT data to the Azure IoT hub asynchronous.

/** IoT Hub Raspberry Pi NodeJS - Microsoft Sample Code - Copyright (c) 2017 - Licensed MIT*/const wpi = require('wiring-pi');
const Client = require('azure-iot-device').Client;
const Message = require('azure-iot-device').Message;
const Protocol = require('azure-iot-device-mqtt').Mqtt;
const BME280 = require('bme280-sensor');
const BME280_OPTION = {
 i2cBusNo: 1, // defaults to 1 i2cAddress: BME280.BME280_DEFAULT_I2C_ADDRESS() // defaults to 0x77};
const connectionString = 'HostName=d365-iot-scm.azure-devices.net;DeviceId=SimulatedRaspberryPi;SharedAccessKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
const LEDPin = 4;
var sendingMessage = false;
var messageId = 0;
var client, sensor;
var blinkLEDTimeout = null;
function getMessage(cb) {
 messageId++;
 sensor.readSensorData()
 .then(function (data) {
 var milliseconds = Date.now();
 var obj = {
 "timestamp": milliseconds,
 "id": "M1225.PartOut",
 "value": 1,
 "messageId": messageId,
 "payload": [
 {
 "timestamp": milliseconds,
 "id": "M1225.Temp",
 "value": data.temperature_C },
 {
 "timestamp": milliseconds,
 "id": "IoTInt.M1225.PartOut",
 "value": 1 },
 {
 "timestamp": milliseconds,
 "id": "IoTInt.M3117.Humidity",
  "value": data.humidity },
 {
 "timestamp": milliseconds,
 "id": "IoTInt.M3117.PartOut",
 "value": 1 },
 {
 "timestamp": milliseconds,
 "id": "IoTInt.M3117.Temp",
 "value": data.temperature_C },
 {
 "timestamp": milliseconds,
 "id": "M1226.Humidity",
  "value": data.humidity }
 ]
 };
 cb(JSON.stringify(obj), data.temperature_C > 30);
 })
 .catch(function (err) {
 console.error('Failed to read out sensor data: ' + err);
 });
 }
function sendMessage() {
 if (!sendingMessage) { return; }
 getMessage(function (content, temperatureAlert) {
 var message = new Message(content);
 message.properties.add('temperatureAlert', temperatureAlert.toString());
 console.log('Sending message: ' + content);
 client.sendEvent(message, function (err) {
 if (err) {
 console.error('Failed to send message to Azure IoT Hub');
 } else {
 blinkLED();
 console.log('Message sent to Azure IoT Hub');
  }
 });
 });
}
function onStart(request, response) {
 console.log('Try to invoke method start(' + request.payload + ')');
 sendingMessage = true;
 response.send(200, 'Successully start sending message to cloud', function (err) {
 if (err) {
 console.error('[IoT hub Client] Failed sending a method response:\n' + err.message);
 }
 });
}
function onStop(request, response) {
 console.log('Try to invoke method stop(' + request.payload + ')');
 sendingMessage = false;
 response.send(200, 'Successully stop sending message to cloud', function (err) {
 if (err) {
 console.error('[IoT hub Client] Failed sending a method response:\n' + err.message);
 }
 });
}
function receiveMessageCallback(msg) {
 blinkLED();
 var message = msg.getData().toString('utf-8');
 client.complete(msg, function () {
 console.log('Receive message: ' + message);
 });
}
function blinkLED() {
 // Light up LED for 500 ms if(blinkLEDTimeout) {
 clearTimeout(blinkLEDTimeout);
 }
 wpi.digitalWrite(LEDPin, 1);
 blinkLEDTimeout = setTimeout(function () {
 wpi.digitalWrite(LEDPin, 0);
 }, 500);
}
// set up wiringwpi.setup('wpi');
wpi.pinMode(LEDPin, wpi.OUTPUT);
sensor = new BME280(BME280_OPTION);
sensor.init()
 .then(function () {
 sendingMessage = true;
 })
 .catch(function (err) {
 console.error(err.message || err);
 });
// create a clientclient = Client.fromConnectionString(connectionString, Protocol);
client.open(function (err) {
 if (err) {
 console.error('[IoT hub Client] Connect error: ' + err.message);
 return;
 }
 // set C2D and device method callback client.onDeviceMethod('start', onStart);
 client.onDeviceMethod('stop', onStop);
 client.on('message', receiveMessageCallback);
 setInterval(sendMessage, 2000);
});

Before we can use the above project we need to register a new device in the IoT hub. That said, we create a device identity in the identity registry in the IoT hub. A device cannot connect to a hub unless it has an entry in the identity registry.

  1. In your IoT hub navigation menu, open IoT Devices, then select New to add a device in your IoT hub.

  2. In Create a device, provide a name for your new device, such as myDeviceId, and select Save. This action creates a device identity for your IoT hub.

  3. After the device is created, open the device from the list in the IoT devices pane. Copy the Primary Connection String to use later.

To run the above raspberry pi project now in connection with the Azure IoT Hub on Pi web simulator, reference the the Azure IoT hub device connection string in your pi project.


You should see the following output that shows the sensor data and the messages that are sent to your IoT hub


17. Monitor scenarios in Microsoft Dynamics 365 Supply Chain Management

You can monitor IoT Intelligence processing from several places:

  • Modules > Production control > Inquiries and reports > IoT Intelligence > Notifications – View the list of unresolved notifications.

  • Modules > Production control > Inquiries and reports > IoT Intelligence > Closed notifications – View the list of notifications that have been resolved or dismissed.

  • Modules > Production control > Inquiries and reports > IoT Intelligence > Metric keys – View the metric keys for the Resource Status times series charts.

  • Modules > Production control > Manufacturing execution > Resource status – Track specific metrics by using the Configure dialog box. If a scenario detects an exception, a notification shows the details of the exception.

  • Workspaces > Production floor management > Notifications – View the list of unresolved notifications.


Demonstration and final result

To sum it up, the following is set up now:

  • Raspberry pi simulator - We are using the Raspberry pi simulator to send the data to Azure IOT Hub.

  • Azure resources and secrets:

  • IoT Hub

  • Redis cache

  • Key vault

  • IoT D365FO add-in via LCS.

  • Enabled the outage/downtime IoT scenarios in D365FO via Production control/IoT Intelligence:

See results in Redis cache: (Signal is sending)

See results in D365FO: (heartbeat is received in D365FO)