readme and device code changes

This commit is contained in:
Ian Hollier 2021-02-16 10:01:23 -08:00
Родитель c3f94d4cb5
Коммит c6095d0bc3
4 изменённых файлов: 96 добавлений и 7 удалений

Просмотреть файл

@ -40,9 +40,10 @@ Format expected by IoT Central:
# Prerequisites # Prerequisites
1. Have a working [IoT Central application](https://apps.azureiotcentral.com/myapps). 1. Node.js installed for running the sample device code [node.js install files](https://nodejs.org/en/)
2. Have a working Azure IoT Central Bridge setup to implement this example against. To do this follow the tutorial [Build the IoT Central device bridge to connect other IoT clouds to IoT Central](https://docs.microsoft.com/en-us/azure/iot-central/core/howto-build-iotc-device-bridge). 2. Have a working [IoT Central application](https://apps.azureiotcentral.com/myapps).
3. Get an application API key from the [Open Weather service](https://openweathermap.org/api). This is free with limited usage of the service, just create an account and follow the instructions to create an application API key that we will need in the next step. 3. Have a working Azure IoT Central Bridge setup to implement this example against. To do this follow the tutorial [Build the IoT Central device bridge to connect other IoT clouds to IoT Central](https://docs.microsoft.com/en-us/azure/iot-central/core/howto-build-iotc-device-bridge).
4. Get an application API key from the [Open Weather service](https://openweathermap.org/api). This is free with limited usage of the service, just create an account and follow the instructions to create an application API key that we will need in the next step.
# Implementing the compute pipeline # Implementing the compute pipeline
@ -62,3 +63,75 @@ Once the above steps are completed return to the Azure Function Overview page an
# Setting up the Azure IoT Central application # Setting up the Azure IoT Central application
Assuming you have created an Azure IoT Central account in the prerequisite step above we now need to add a device model and setup the data export. First lets add the device template to our application by going to our application and following the list of instructions below:
* Select "Device templates" in the laft hand navigation rail.
* Click the '+ New" link top left and select "IoT device" and click "Next:Customize".
* Give your template a name (say "compute"), do not check the "Gateway device" box and click "Next: Review".
* Now click "Create"
You have created an empty device template which we now need to fill with a device model by:
* Select "Import a model" and choose the "model.json" file from this repository (same directory as this README file)
* The model will be imported and you will see the imported description of the data shown
* Publish the model so it can be used in your application by clicking the "Publish" link at the top of the page
You now have a working device model that you can further enhance by adding Views if you feel like it but is not necessary to see this sample in operation. More information on device templates in IoT Central can be found in the documentation [here](https://docs.microsoft.com/en-us/azure/iot-central/core/concepts-device-templates).
Let's now setup the data export to send data to our Azure Function:
* Select "Data export" in the laft hand navigation rail.
* Click the '+ New export" link top left and give your data export a name (say "compute export").
* We need to add a couple of filters so we only export the data we want computation done on so click the "+ Filter" and select item "Device template", select Operator "Equals", and select "Value" and the name of the device template you just created (in my example above "compute").
* We also need a message filter so we can differentiate computed values from none-computed. This will prevent us from sending computed values back through for computed in the engine.js file of the Azure Function we added code to add a message property called "computed" we should only export data to our function if that value is NOT present. Select "+ Message property filter" and enter the name value "computed", then for operator select "Does not exist".
* We do not need any enrichments so lets create a destination to our Azure Function
* Click the link under "Destinations" called "create a new one". Provide a destination name (Say "compute function"), for "Destination type" select "Webhook". For the Callback URL select paste in the URL for the azure function (this can be found in the overview screen for the bridge function you created by clicking "Get Function Url"). The "Authorization" should be left as "No Auth". Now click "Create" and you have created the link to the Azure Function.
* Click "+ Destination" and select the destination you just created ("compute function").
* click "Save" at the top of the page and after a minute or so you should see the "Export status" show as Healthy.
We now have all the necessary setup done on our IoT Central application, lets send some telemetry data from a device and see if it works.
# Sending data from a device and seeing it get transformed and computed
A sample device is included in the repository to send random ranged data to IoT Central in the CSV data format. The device code can be found in the file "device/device.js" and is run using node.js. First we need to provide the device with some information so it can connect to our IoT Central application.
In the device.js file the following information needs to be provided:
```
// These values need to be filled in from your Azure IoT Central application
//
const scopeId = "<IoT Central Scope Id value>";
const groupSasKey = "<IoT Central Group SAS key>";
//
/////////////////////////////////////////////////////////////////////////////
```
The Scope Id and the Group SAS key can be found in the IoT Central application by clicking the Administration -> Device connection in the left hand navigation. Copy the ID Scope value and the "SAS-IoT-Devices" primary key into the code replacing the place holder text. Save the file and from the command line in the "iot-central-compute\device" directory issue the following command to run the device:
```
node device.js
```
You should see the following similar output:
```
registration succeeded
assigned hub=iotc-2bd611b0-755c-438a-b714-f01f43aab2ef.azure-devices.net
deviceId=computeDevice
Client connected
send status: MessageEnqueued [{"data":"33.23, 69.09, 30.7213, -61.1192"}]
send status: MessageEnqueued [{"data":"2.43, 75.86, -2.6358, 162.935"}]
send status: MessageEnqueued [{"data":"6.19, 76.55, -14.3538, -82.314"}]
send status: MessageEnqueued [{"data":"33.26, 48.01, 71.9172, 48.6606"}]
send status: MessageEnqueued [{"data":"40.5, 36.41, 14.6043, 14.079"}]
```
If you now check your application you should see a device called "computeDevice" under the "Compute" device template name:
![Device computeDevice showing up]()
Clicking on the devie and looking at the Raw data view we should now see two different telemetry lines one after the other showing up around every five seconds:
![telemtry coming through]()
We can see the device CSV formatted telemetry come through first then the computed telemetry coming through after with the temperature in degrees fahrenheit and the additional weather service data all in JSON format and correctly recognized and interpreted by the IoT Central application.

Двоичные данные
assets/deviceshowingup.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 33 KiB

Двоичные данные
assets/telemetry.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 72 KiB

Просмотреть файл

@ -1,5 +1,6 @@
'use strict'; 'use strict';
const crypto = require('crypto');
const iotHubTransport = require('azure-iot-device-mqtt').Mqtt; const iotHubTransport = require('azure-iot-device-mqtt').Mqtt;
const Client = require('azure-iot-device').Client; const Client = require('azure-iot-device').Client;
const Message = require('azure-iot-device').Message; const Message = require('azure-iot-device').Message;
@ -10,15 +11,30 @@ const ProvisioningDeviceClient = require('azure-iot-provisioning-device').Provis
const chance = new require('chance')(); const chance = new require('chance')();
// //
// For the public clouds the address of the provisioning host would be: global.azure-devices-provisioning.net // For the public clouds the address of the provisioning host is global.azure-devices-provisioning.net, this will be different in private and soverign clouds
// //
const provisioningHost = "global.azure-devices-provisioning.net"; const provisioningHost = "global.azure-devices-provisioning.net";
const scopeId = "0ne0005C8ED"; // These values need to be filled in from your Azure IoT Central application
//
const scopeId = "<IoT Central Scope Id value>";
const groupSasKey = "<IoT Central Group SAS key>";
//
/////////////////////////////////////////////////////////////////////////////
const deviceId = "computeDevice"; const deviceId = "computeDevice";
const deviceKey = "MuhTABbh8eWK4vJXJR92hlef9uBm16bnNAgRolAJQNs=";
const modelId = "dtmi:computeModel:compute;1"; const modelId = "dtmi:computeModel:compute;1";
// calculate the device key from the deviceId and group SAS key
function getDeviceKey(deviceId, groupSasKey) {
return crypto.createHmac('SHA256', Buffer.from(groupSasKey, 'base64'))
.update(deviceId)
.digest()
.toString('base64');
}
const deviceKey = getDeviceKey(deviceId, groupSasKey);
const provisioningSecurityClient = new SymmetricKeySecurityClient(deviceId, deviceKey); const provisioningSecurityClient = new SymmetricKeySecurityClient(deviceId, deviceKey);
const provisioningClient = ProvisioningDeviceClient.create(provisioningHost, scopeId, new ProvisioningTransport(), provisioningSecurityClient); const provisioningClient = ProvisioningDeviceClient.create(provisioningHost, scopeId, new ProvisioningTransport(), provisioningSecurityClient);
provisioningClient.setProvisioningPayload(`{ "iotcModelId": "${modelId}" }`); provisioningClient.setProvisioningPayload(`{ "iotcModelId": "${modelId}" }`);
@ -45,7 +61,7 @@ provisioningClient.register(function(err, result) {
var message = new Message(`{"data":"${chance.floating({min: -20, max: 50, fixed: 2})}, ${chance.floating({min: 0, max: 100, fixed: 2})}, ${chance.latitude({fixed: 4})}, ${chance.longitude({fixed: 4})}"}`); var message = new Message(`{"data":"${chance.floating({min: -20, max: 50, fixed: 2})}, ${chance.floating({min: 0, max: 100, fixed: 2})}, ${chance.latitude({fixed: 4})}, ${chance.longitude({fixed: 4})}"}`);
hubClient.sendEvent(message, function(err, res) { hubClient.sendEvent(message, function(err, res) {
if (err) console.log('send error: ' + err.toString()); if (err) console.log('send error: ' + err.toString());
if (res) console.log('send status: ' + res.constructor.name); if (res) console.log('send status: ' + res.constructor.name + ' [' + message.data + ']');
}); });
}, 5000); }, 5000);
} }