You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 10:27:50