Node.js模拟遥测数据从IoT Hub到ADT Explorer接收异常求助
问题:IoT Hub模拟数据转发至ADT后无法在ADT Explorer查询到
刚接触数字孪生/IoT技术,目前基于IoT Hub VS Code扩展的模拟数据搭建数字孪生方案。已成功将模拟遥测数据发送至IoT Hub,但通过Azure Function转发到ADT实例后,ADT Explorer无法查询到这些数据。不过运行代码时,能看到消息被ADT接收且函数已执行。
推测可能的原因有三点:Azure Function代码、ADT中的DTDL模型、Event Grid。已多次检查代码、参考GPT验证,基于之前可用的孪生模型修改DTDL,Event Grid配置与之前项目一致,还尝试过在新环境重新部署,但问题仍未解决。
Node.js模拟设备代码
// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. 'use strict'; // The device connection string to authenticate the device with your IoT hub. // // NOTE: // For simplicity, this sample sets the connection string in code. // In a production environment, the recommended approach is to use // an environment variable to make it available to your application // or use an HSM or an x509 certificate. // https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-security var connectionString = 'My Connection String'; // Using the Node.js Device SDK for IoT Hub: // https://github.com/Azure/azure-iot-sdk-node // Run 'npm install azure-iot-device-mqtt' to install the required libraries for this application // The sample connects to a device-specific MQTT endpoint on your IoT Hub. var Mqtt = require('azure-iot-device-mqtt').Mqtt; var DeviceClient = require('azure-iot-device').Client; var Message = require('azure-iot-device').Message; var client = DeviceClient.fromConnectionString(connectionString, Mqtt); // Print results. function printResultFor(op) { return function printResult(err, res) { if (err) console.log(op + ' error: ' + err.toString()); if (res) console.log(op + ' status: ' + res.constructor.name); }; } // Create a message and send it to the IoT hub every second setInterval(function(){ // Simulate telemetry. var temperature = 20 + (Math.random() * 15); var humidity = 60 + (Math.random() * 20); var flowrate = 100 + (Math.random() * 50); var wattage = 60 + (Math.random() * 40); var oillevel = 50 + (Math.random() * 50); // Add the telemetry to the message body. var data = JSON.stringify({ temperature: temperature, humidity: humidity, flowrate: flowrate, wattage: wattage, oillevel: oillevel }); var message = new Message(data); // Add a custom application property to the message. // An IoT hub can filter on these properties without access to the message body. message.properties.add('temperatureAlert', (temperature > 30) ? 'true' : 'false'); console.log('Sending message: ' + message.getData()); // Send the message. client.sendEvent(message, printResultFor('send')); }, 1000);
Azure Function代码(C#)
// Default URL for triggering event grid function in the local environment. // http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname} using System; using Azure; using System.Net.Http; using Azure.Core.Pipeline; using Azure.DigitalTwins.Core; using Azure.Identity; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.EventGrid; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Azure.Messaging.EventGrid; using System.Diagnostics; using System.Text; namespace IotHubtoTwins { public class IoTHubtoTwinsVSCode { private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL"); private static readonly HttpClient httpClient = new HttpClient(); [FunctionName("IoTHubtoTwins")] // While async void should generally be used with caution, it's not uncommon for Azure function apps, since the function app isn't awaiting the task. #pragma warning disable AZF0001 // Suppress async void error public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) #pragma warning restore AZF0001 // Suppress async void error { if (adtInstanceUrl == null) log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); try { // Authenticate with Digital Twins var cred = new DefaultAzureCredential(); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred); log.LogInformation($"ADT service client connection created."); if (eventGridEvent != null && eventGridEvent.Data != null) { log.LogInformation(eventGridEvent.Data.ToString()); // <Find_device_ID_and_telemetry> JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"]; // <added for Base64 to string to object conversion> var base64EncodedBytes = System.Convert.FromBase64String((string)deviceMessage["body"]); string deviceMessagedecoded = System.Text.Encoding.UTF8.GetString(base64EncodedBytes); JObject decodedObject = (JObject)JsonConvert.DeserializeObject(deviceMessagedecoded); var temperature = decodedObject["temperature"]; var humidity = decodedObject["humidity"]; var flowRate = decodedObject["flowrate"]; var oilLevel = decodedObject["oillevel"]; var wattage = decodedObject["wattage"]; // </Find_device_ID_and_telemetry> log.LogInformation($"Device:{deviceId} Telemetry data: Temperature={temperature}, Humidity={humidity}, FlowRate={flowRate}, OilLevel={oilLevel}, Wattage={wattage}"); // <Update_twin_with_device_telemetry> var updateTwinData = new JsonPatchDocument(); updateTwinData.AppendReplace("/Temperature", temperature.Value<double>()); updateTwinData.AppendReplace("/Humidity", humidity.Value<double>()); updateTwinData.AppendReplace("/FlowRate", flowRate.Value<double>()); updateTwinData.AppendReplace("/OilLevel", oilLevel.Value<double>()); updateTwinData.AppendReplace("/Wattage", wattage.Value<double>()); await client.UpdateDigitalTwinAsync(deviceId, updateTwinData).ConfigureAwait(false); // </Update_twin_with_device_telemetry> } } catch (Exception ex) { log.LogError($"Error in ingest function: {ex.Message}"); } } } }
内容的提问来源于stack exchange,提问作者Craig BH
相关产品推荐
相关产品推荐

