将设备连接到远程监视预配置解决方案 (Node.js)
方案概述
在此方案中,创建会将以下遥测数据发送到远程监视预配置解决方案的设备:
- 外部温度
- 内部温度
- 湿度
为简单起见,设备上的代码将生成示例值,但我们建议通过将实际传感器连接到设备并发送实际的遥测数据来扩展此示例。
该设备还能响应从解决方案仪表板中调用的方法,以及在解决方案仪表板中设置的所需属性值。
要完成此教程,需要一个有效的 Azure 帐户。 如果没有帐户,只需花费几分钟就能创建一个免费试用帐户。 有关详细信息,请参阅 Azure 免费试用。
开始之前
在为设备编写任何代码之前,必须先预配远程监视预配置解决方案,并在该解决方案中预配新的自定义设备。
预配远程监视预配置解决方案
本教程中创建的设备会将数据发送到远程监视预配置解决方案的实例中。 如果尚未在 Azure 帐户中预配远程监视预配置解决方案,请使用以下步骤:
- 在 https://www.azureiotsolutions.com/ 页上,单击“”+以创建解决方案。
- 单击“远程监视”面板上的“选择”创建解决方案。
- 在“创建远程监视解决方案”页上,输入所选的解决方案名称,选择要部署到的区域,并选择要使用的 Azure 订阅。 然后单击“创建解决方案”。
- 等待预配过程完成。
警告
预配置的解决方案使用可计费的 Azure 服务。 当使用完预配置的解决方案之后,请务必将它从订阅中删除,以避免产生任何不必要的费用。 通过访问 https://www.azureiotsolutions.com/ 页,即可将预配置的解决方案从订阅中完全删除。
远程监视解决方案的预配过程完成之后,请单击“启动”,在浏览器中打开解决方案仪表板。
在远程监视解决方案中预配设备
注意
如果已在解决方案中预配了设备,则可以跳过此步骤。 创建客户端应用程序时需要知道设备凭据。
对于连接到预配置解决方案的设备,该设备必须使用有效的凭据将自身标识到 IoT 中心。 可以从解决方案仪表板中检索设备凭据。 在本教程中,稍后会在客户端应用程序中添加设备凭据。
若要在远程监视解决方案中添加设备,请在解决方案仪表板中完成以下步骤:
在仪表板左下角,单击“添加设备”。
在“自定义设备”面板中,单击“新增”。
选择“让我定义我自己的设备 ID”。 输入设备 ID(例如“mydevice”),单击“检查 ID”验证该名称是否尚未使用,并单击“创建”预配设备。
记下设备凭据(设备 ID、IoT 中心主机名和设备密钥)。 客户端应用程序需要这些值才能连接到远程监视解决方案。 然后单击“完成”。
在解决方案仪表板中的设备列表中选择设备。 接着,在“设备详细信息”面板中,单击“启用设备”。 设备状态现在为“正在运行”。 远程监视解决方案现在可以从设备接收遥测数据,并在设备上调用方法。
创建 node.js 示例解决方案
请确保已在开发计算机上安装 Node.js 版本 0.11.5 或更高版本。 若要检查版本,可以在命令行中运行 node --version
。
在开发计算机上,创建名为 RemoteMonitoring 的文件夹。 导航到命令行环境中的此文件夹。
运行以下命令,以便下载并安装完成示例应用所需的包:
npm init npm install azure-iot-device azure-iot-device-mqtt --save
在 RemoteMonitoring 文件夹中,创建名为 remote_monitoring.js 的文件。 在文本编辑器中打开此文件。
在 remote_monitoring.js 文件中,添加以下
require
语句:'use strict'; var Protocol = require('azure-iot-device-mqtt').Mqtt; var Client = require('azure-iot-device').Client; var ConnectionString = require('azure-iot-device').ConnectionString; var Message = require('azure-iot-device').Message;
在
require
语句之后添加以下变量声明。 将占位符值 [Device Id] 和 [Device Key] 替换为在远程监视解决方案仪表板中记下的设备值。 使用解决方案仪表板中的 IoT 中心主机名替换 [IoTHub Name]。 例如,如果 IoT 中心主机名是 contoso.azure-devices.net,则将 [IoTHub Name] 替换为 contoso:var connectionString = 'HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]'; var deviceId = ConnectionString.parse(connectionString).DeviceId;
添加以下变量,定义一些基遥测数据:
var temperature = 50; var humidity = 50; var externalTemperature = 55;
添加以下帮助程序函数,以便列显操作结果:
function printErrorFor(op) { return function printError(err) { if (err) console.log(op + ' error: ' + err.toString()); }; }
添加以下帮助程序函数,用于随机化遥测值:
function generateRandomIncrement() { return ((Math.random() * 2) - 1); }
为设备在启动时发送的 DeviceInfo 对象添加以下定义:
var deviceMetaData = { 'ObjectType': 'DeviceInfo', 'IsSimulatedDevice': 0, 'Version': '1.0', 'DeviceProperties': { 'DeviceID': deviceId, 'HubEnabledState': 1 } };
为设备孪生报告的值添加以下定义。 该定义包括对设备支持的直接方法的说明:
var reportedProperties = { "Device": { "DeviceState": "normal", "Location": { "Latitude": 47.642877, "Longitude": -122.125497 } }, "Config": { "TemperatureMeanValue": 56.7, "TelemetryInterval": 45 }, "System": { "Manufacturer": "Contoso Inc.", "FirmwareVersion": "2.22", "InstalledRAM": "8 MB", "ModelNumber": "DB-14", "Platform": "Plat 9.75", "Processor": "i3-9", "SerialNumber": "SER99" }, "Location": { "Latitude": 47.642877, "Longitude": -122.125497 }, "SupportedMethods": { "Reboot": "Reboot the device", "InitiateFirmwareUpdate--FwPackageURI-string": "Updates device Firmware. Use parameter FwPackageURI to specifiy the URI of the firmware file" }, }
添加以下函数以处理 Reboot 直接方法调用:
function onReboot(request, response) { // Implement actual logic here. console.log('Simulated reboot...'); // Complete the response response.send(200, "Rebooting device", function(err) { if(!!err) { console.error('An error occurred when sending a method response:\n' + err.toString()); } else { console.log('Response to method \'' + request.methodName + '\' sent successfully.' ); } }); }
添加以下函数以处理 InitiateFirmwareUpdate 直接方法调用。 该直接方法使用参数指定要下载的固件映像的位置,并在设备上异步启动固件更新:
function onInitiateFirmwareUpdate(request, response) { console.log('Simulated firmware update initiated, using: ' + request.payload.FwPackageURI); // Complete the response response.send(200, "Firmware update initiated", function(err) { if(!!err) { console.error('An error occurred when sending a method response:\n' + err.toString()); } else { console.log('Response to method \'' + request.methodName + '\' sent successfully.' ); } }); // Add logic here to perform the firmware update asynchronously }
添加以下代码,创建客户端实例:
var client = Client.fromConnectionString(connectionString, Protocol);
添加以下代码来执行下述操作:
- 打开连接。
- 发送 DeviceInfo 对象。
- 设置所需属性的处理程序。
- 发送报告的属性。
- 为直接方法注册处理程序。
- 开始发送遥测。
client.open(function (err) { if (err) { printErrorFor('open')(err); } else { console.log('Sending device metadata:\n' + JSON.stringify(deviceMetaData)); client.sendEvent(new Message(JSON.stringify(deviceMetaData)), printErrorFor('send metadata')); // Create device twin client.getTwin(function(err, twin) { if (err) { console.error('Could not get device twin'); } else { console.log('Device twin created'); twin.on('properties.desired', function(delta) { console.log('Received new desired properties:'); console.log(JSON.stringify(delta)); }); // Send reported properties twin.properties.reported.update(reportedProperties, function(err) { if (err) throw err; console.log('twin state reported'); }); // Register handlers for direct methods client.onDeviceMethod('Reboot', onReboot); client.onDeviceMethod('InitiateFirmwareUpdate', onInitiateFirmwareUpdate); } }); // Start sending telemetry var sendInterval = setInterval(function () { temperature += generateRandomIncrement(); externalTemperature += generateRandomIncrement(); humidity += generateRandomIncrement(); var data = JSON.stringify({ 'DeviceID': deviceId, 'Temperature': temperature, 'Humidity': humidity, 'ExternalTemperature': externalTemperature }); console.log('Sending device event data:\n' + data); client.sendEvent(new Message(data), printErrorFor('send event')); }, 5000); client.on('error', function (err) { printErrorFor('client')(err); if (sendInterval) clearInterval(sendInterval); client.close(printErrorFor('client.close')); }); } });
保存对 remote_monitoring.js 文件的更改。
在命令提示符处运行以下命令,启动示例应用程序:
node remote_monitoring.js
在仪表板中查看设备遥测数据
远程监视解决方案中的仪表板可让用户查看设备发送到 IoT 中心的遥测数据。
在浏览器中,返回到远程监视解决方案仪表板,单击左侧面板中的“设备”导航到“设备列表”。
在“设备列表”中,应会看到设备状态为“正在运行”。 如果不是,请在“设备详细信息”面板中单击“启用设备”。
单击“仪表板”返回到仪表板,在“要查看的设备”下拉列表中选择设备,以查看其遥测数据。 示例应用程序的遥测数据是 50 个单位的内部温度、55 个单位的外部温度,以及 50 个单位的湿度。
在设备上调用方法
远程监视解决方案中的仪表板可让用户通过 IoT 中心在设备上调用方法。 例如在远程监视解决方案中,用户可以调用方法来模拟重新启动设备。
在远程监视解决方案仪表板中,单击左侧面板中的“设备”导航到“设备列表”。
在“设备列表”中,单击设备的“设备 ID”。
在“设备详细信息”面板中,单击“方法”。
在“方法”下拉列表中,选择“InitiateFirmwareUpdate”,并在“FWPACKAGEURI”中输入虚拟 URL。 单击“调用方法”在设备上调用方法。
设备处理方法时,可在运行设备代码的控制台中看到一则消息。 方法的结果会被添加到解决方案门户中的历史记录上:
后续步骤
自定义预配置解决方案一文介绍了扩展本示例的一些方法。 可能的扩展包括使用真实传感器和实现其他命令。
可以详细了解 azureiotsuite.com 站点权限。