如何从IoT Hub获取遥测数据并传输到Azure数字孪生。

huangapple go评论59阅读模式
英文:

how to get telemetry data from iothub to Azure Digital Twins

问题

要将遥测数据从IOT中心发送到Azure数字孪生,但我无法成功。我已经尝试了Microsoft的完整示例(https://learn.microsoft.com/en-us/azure/digital-twins/how-to-ingest-iot-hub-data)。我应该添加其他内容吗?或者我可以更改什么?

 public static class Function1
    {
        private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL");
        private static readonly HttpClient singletonHttpClientIntance = new HttpClient();

        [FunctionName("IOTHubtoADTwins")]
        public static async Task Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
        {
            if (adtInstanceUrl == null) log.LogError("Application setting \"ADT_SERVICE_URL\" not set");

            try
            {
                var cred = new ManagedIdentityCredential("https://digitaltwins.azure.net");

                var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred,
                new DigitalTwinsClientOptions
                {
                    Transport = new HttpClientTransport(singletonHttpClientIntance)
                });

                log.LogInformation("ADT service client connection created.");

                if (eventGridEvent != null && eventGridEvent.Data != null)
                {
                    JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                    string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                    var Auto = deviceMessage["body"]["Auto"];

                    log.LogInformation($"Device:{deviceId} Auto is: {Auto}");

                    var updateTwinData = new JsonPatchDocument();
                    updateTwinData.AppendReplace("/Auto", Auto.Value<bool>());
                    await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
                }
            }
            catch(Exception ex)
            {
                log.LogError($"Error in ingest function: {ex.Message}"); 
            }
        }
    }

我收到以下错误消息:

2023-05-18T14:41:51Z [Information] Executed 'IOTHubtoADTwins' (Succeeded, Id=e5f6558b-a2f2-4f34-8326-caea78585e4e, Duration=3430ms)
2023-05-18T14:41:53Z [Information] Executing 'IOTHubtoADTwins' (Reason='EventGrid trigger fired at 2023-05-18T14:41:52.9272358+00:00', Id=b8c6c105-03c9-47fa-a5b0-b38b2e05b4f4)
2023-05-18T14:41:53Z [Information] ADT service client connection created.
2023-05-18T14:41:53Z [Information] {"properties":{},"systemProperties":{"iothub-connection-device-id":"Modell","iothub-connection-auth-method":"{"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}","iothub-connection-auth-generation-id":"638200132745402706","iothub-enqueuedtime":"2023-05-18T14:41:52.525Z","iothub-message-source":"Telemetry"},"body":"eyJUZW1wZXJhdHVyIiA6ICIwLjAiLCJIdW1pZGl0eSIgOiAiMC4wIix9"}

2023-05-18T14:41:56Z [Error] Error in ingest function: Cannot access child value on Newtonsoft.Json.Linq.JValue.

谢谢反馈,迄今为止我已经更改了一切,但是收到不同的错误消息:

2023-05-18T22:21:00Z [Error] Error in ingest function: Value cannot be null. (Parameter 'source')

要发送消息,请使用以下Python代码:

import json
from opcua import Client
from time import sleep
from azure.iot.device import IoTHubDeviceClient, Message

# OPC UA Node-IDs
opc_node_ids = {
    "Auto": 'ns=3;s="Send"."Auto"'
}

# OPC UA Client初始化
def opcua_init():
    opcua_client = Client("x")  # 插入OPC UA地址
    while True:
        try:
            print("Trying to connect to the OPC UA server...")
            opcua_client.connect()
            return opcua_client
        except:
            print("Connection failed. Trying again after 5 seconds...")
            sleep(5)

# IoT Hub客户端初始化
def iot_hub_init():
    while True:
        try:
            iot_client = IoTHubDeviceClient.create_from_connection_string("x", websockets=True)  # 插入IoT连接字符串
            print("Trying to connect to the IoT Hub...")
            iot_client.connect()
            return iot_client
        except:
            print("Connection failed. Trying again after 5 seconds...")
            sleep(5)

# 获取OPC UA服务器的数据并返回为JSON字符串
def opcua_get_value(client):
    opcua_data = {}
    for node_name, node_id in opc_node_ids.items():
        ba_node = client.get_node(node_id)
        ba_value = ba_node.get_value()
        ba_displayname = ba_node.get_display_name().to_string()

        opcua_data[ba_displayname] = ba_value

    return json.dumps(opcua_data)

# 周期性获取数据并发送到IoT Hub
def send_cycle(opcua_client, iot_client):
    try:
        while True:
            opcua_value = opcua_get_value(opcua_client)
            print(opcua_value)
            message = Message(opcua_value)
            print("Sending message to IoT Hub: {}".format(message))
            iot_client.send_message(message)
            print("Message sent successfully")
            sleep(5)
    except KeyboardInterrupt:
        print("IoT Hub client sampling stopped")
        opcua_client.disconnect()
        iot_client.disconnect()

# 主函数
if __name__ == '__main__':
    opcua_client = opcua_init()
    iot_client = iot_hub_init()
    send_cycle(opcua_client, iot_client)

然后得到夜间消息已发送的消息:
Sending message to IoT Hub: {"Auto": true}
Message sent successfully

并且在查询时获得:
var Auto = deviceMessage["body"]["Auto"];

我应该在发送之前以不同的方式格式化数据吗?还是应该以不同的方式查询?我是否可以在发送之前以某种方式查看JSON数据?谢谢

英文:

I would like to send the telemetry data from the IOT hub to Azure digital twins, but I can't get it. I have tested the complete example from Microsoft (https://learn.microsoft.com/en-us/azure/digital-twins/how-to-ingest-iot-hub-data) without success. Should I add something else or what can I change?
here is the integration where I think it is missing the Digital Twins as output

如何从IoT Hub获取遥测数据并传输到Azure数字孪生。

Thanks

 public static class Function1
    {
        
        private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable(&quot;ADT_SERVICE_URL&quot;);
        
        private static readonly HttpClient singletonHttpClientIntance = new HttpClient();

        [FunctionName(&quot;IOTHubtoADTwins&quot;)]
        public static async Task Run ([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
        {
           
            if (adtInstanceUrl == null) log.LogError(&quot;Application setting \&quot;ADT_SERVICE_URL\&quot; not set&quot;);

            try
            {
                //log.LogInformation(eventGridEvent.Data.ToString());

                //manager f&#252;r die identity
                var cred = new ManagedIdentityCredential(&quot;https://digitaltwins.azure.net&quot;);

               
                var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred,
                new DigitalTwinsClientOptions
                {
                    Transport = new HttpClientTransport(singletonHttpClientIntance)
                });

            
                log.LogInformation($&quot; ADT service client connection created.&quot;);

            
                if (eventGridEvent != null &amp;&amp; eventGridEvent.Data != null)
                {
                    log.LogInformation(eventGridEvent.Data.ToString());

                    JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());

                    string deviceId = (string)deviceMessage[&quot;systemProperties&quot;][&quot;iothub-connection-device-id&quot;];
                    var Auto = deviceMessage[&quot;body&quot;][&quot;Auto&quot;];

                    log.LogInformation($&quot;Device:{deviceId} Auto is: {Auto}&quot;);

                    var updateTwinData = new JsonPatchDocument();
                    updateTwinData.AppendReplace(&quot;/Auto&quot;, Auto.Value&lt;bool&gt;());
                    await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
                }
            }
            catch(Exception ex)
            {
                log.LogError($&quot;Error in ingest function: {ex.Message}&quot;); 
            }
        }
    }
    

I receive this Error message

2023-05-18T14:41:51Z [Information] Executed 'IOTHubtoADTwins' (Succeeded, Id=e5f6558b-a2f2-4f34-8326-caea78585e4e, Duration=3430ms)
2023-05-18T14:41:53Z [Information] Executing 'IOTHubtoADTwins' (Reason='EventGrid trigger fired at 2023-05-18T14:41:52.9272358+00:00', Id=b8c6c105-03c9-47fa-a5b0-b38b2e05b4f4)
2023-05-18T14:41:53Z [Information] ADT service client connection created.
2023-05-18T14:41:53Z [Information] {"properties":{},"systemProperties":{"iothub-connection-device-id":"Modell","iothub-connection-auth-method":"{\u0022scope\u0022:\u0022device\u0022,\u0022type\u0022:\u0022sas\u0022,\u0022issuer\u0022:\u0022iothub\u0022,\u0022acceptingIpFilterRule\u0022:null}","iothub-connection-auth-generation-id":"638200132745402706","iothub-enqueuedtime":"2023-05-18T14:41:52.525Z","iothub-message-source":"Telemetry"},"body":"eyJUZW1wZXJhdHVyIiA6ICIwLjAiLCJIdW1pZGl0eSIgOiAiMC4wIix9"}

2023-05-18T14:41:56Z [Error] Error in ingest function: Cannot access child value on Newtonsoft.Json.Linq.JValue.

Thanks for the feedback, have changed everything so far but get a different error message:

2023-05-18T22:21:00Z [Error] Error in ingest function: Value cannot be null. (Parameter 'source')

to send the message user the following Python code:

import json
from opcua import Client
from time import sleep
from azure.iot.device import IoTHubDeviceClient, Message

# OPC UA Node-IDs
opc_node_ids = {
    &quot;Auto&quot;: &#39;ns=3;s=&quot;Send&quot;.&quot;Auto&quot;&#39;
}

# OPC UA Client initialisieren
def opcua_init():
    opcua_client = Client(&quot;x&quot;)  # OPC UA-Adresse einsetzen
    while True:
        try:
            print(&quot;Trying to connect to the OPC UA server...&quot;)
            opcua_client.connect()
            return opcua_client
        except:
            print(&quot;Connection failed. Trying again after 5 seconds...&quot;)
            sleep(5)

# IoT Hub-Client initialisieren
def iot_hub_init():
    while True:
        try:
            iot_client = IoTHubDeviceClient.create_from_connection_string(&quot;x&quot;, websockets=True)  # IoT-Verbindungszeichenfolge einsetzen
            print(&quot;Trying to connect to the IoT Hub...&quot;)
            iot_client.connect()
            return iot_client
        except:
            print(&quot;Connection failed. Trying again after 5 seconds...&quot;)
            sleep(5)

# Daten von OPC UA-Server abrufen und als JSON-String zur&#252;ckgeben
def opcua_get_value(client):
    opcua_data = {}
    for node_name, node_id in opc_node_ids.items():
        ba_node = client.get_node(node_id)
        ba_value = ba_node.get_value()
        ba_displayname = ba_node.get_display_name().to_string()

        opcua_data[ba_displayname] = ba_value

    return json.dumps(opcua_data)

# Zyklisch Daten abrufen und an IoT Hub senden
def send_cycle(opcua_client, iot_client):
    try:
        while True:
            opcua_value = opcua_get_value(opcua_client)
            print(opcua_value)
            message = Message(opcua_value)
            print(&quot;Sending message to IoT Hub: {}&quot;.format(message))
            iot_client.send_message(message)
            print(&quot;Message sent successfully&quot;)
            sleep(5)
    except KeyboardInterrupt:
        print(&quot;IoT Hub client sampling stopped&quot;)
        opcua_client.disconnect()
        iot_client.disconnect()

# Hauptfunktion
if __name__ == &#39;__main__&#39;:
    opcua_client = opcua_init()
    iot_client = iot_hub_init()
    send_cycle(opcua_client, iot_client)

then get the message that the night message was sent:
Sending message to IoT Hub: {"Auto": true}
Message sent successfully

and to query I get:
var Auto = deviceMessage[&quot;body&quot;][&quot;Auto&quot;];

should i format the data differently before i send it? or should i query it differently? can i somehow see the jsondata? Thanks

答案1

得分: 1

以下是要翻译的内容:

"the code sample provided in the [Tutorial] works as expected in pushing the data from IoT Hub to Azure Digital Twin. Looks like you are trying to retrieve a property from the Telemetry data which does not exist. That is likely the cause of the error you are facing.

To get a better understanding of the issue, inspect the following elements-

  1. The section Test with simulated IoT data uses Device Simulator project. Open AzureIoTHub.cs file under the project and inspect the line 54 of the sample where the telemetry data being simulated is set. 如何从IoT Hub获取遥测数据并传输到Azure数字孪生。

  2. The above highlighted property is the telemetry being transmitted by IoT Hub and it should match with the field we are trying to retrieve from IOTHubtoADTwins function through the line of code var Auto = deviceMessage[&quot;body&quot;][&quot;Auto&quot;];. Looks like you are trying to fetch a property called "Auto" from the message. Make sure that it being sent by the device simulator code.

  3. The following line of code updateTwinData.AppendReplace(&quot;/Auto&quot;, Auto.Value&lt;bool&gt;()); is used to set the property value of the Azure Digital Twin. Inspecting the model you have provided in the comments, there is no Property on your Azure Digital Twin with a name Auto. Fix it to make sure the data can be transferred.

  4. The following line of code await client.UpdateDigitalTwinAsync(deviceId, updateTwinData); is used to update the corresponding digital Twin that matches the digital twin with the deviceId. Note that the deviceId can be different from your Azure IoTHub device ID. Make sure you set the same device ID in your code to the value which you have used for --twin-id property while creation using a similar statement like this az dt twin create --dt-name &lt;instance-hostname-or-name&gt; --dtmi &quot;dtmi:contosocom:DigitalTwins:Thermostat;1&quot; --twin-id thermostat67 --properties &#39;{&quot;Temperature&quot;: 0.0}&#39;

If you are using a Python SDK, you can formulate the message structure as follows to make sure the telemetry data sent is in JSON format.

MSG_TXT = '{{"temperature": {temperature},"humidity": {humidity}, "timesent": {timesent}}}'
temperature = TEMPERATURE + (random.random() * 15)
humidity = HUMIDITY + (random.random() * 20)
x = datetime.now().isoformat()
timesent = dumps(datetime now(), default=json_serial)
msg_txt_formatted = MSG_TXT.format(
temperature=temperature, humidity=humidity, timesent=timesent)
message = Message(msg_txt_formatted, content_encoding="utf-8", content_type="application/json")
client.send_message(message)

Once you have addressed all there parameters, you should push the data to Azure Digital Twin without any issues. Please refer the below image showing the data received on Azure Digital Twin using the same piece of code. 如何从IoT Hub获取遥测数据并传输到Azure数字孪生。

Please also refer to the thread Telemetry Data from IOT hub not pushing to azure function and not reflecting to Digital Twin? where a similar issue has been discussed.

英文:

the code sample provided in the [Tutorial] works as expected in pushing the data from IoT Hub to Azure Digital Twin. Looks like you are trying to retrieve a property from the Telemetry data which does not exist. That is likely the cause of the error you are facing.

To get a better understanding of the issue, inspect the following elements-

  1. The section Test with simulated IoT data uses Device Simulator project. Open AzureIoTHub.cs file under the project and inspect the line 54 of the sample where the telemetry data being simulated is set.
    如何从IoT Hub获取遥测数据并传输到Azure数字孪生。
  2. The above highlighted property is the telemetry being transmitted by IoT Hub and it should match with the field we are trying to retrieve from IOTHubtoADTwins function through the line of code var Auto = deviceMessage[&quot;body&quot;][&quot;Auto&quot;];. Looks like you are trying to fetch a property called "Auto" from the message. Make sure that it being sent by the device simulator code.
  3. The following line of code updateTwinData.AppendReplace(&quot;/Auto&quot;, Auto.Value&lt;bool&gt;()); is used to set the property value of the Azure Digital Twin. Inspecting the model you have provided in the comments, there is no Property on your Azure Digital Twin with a name Auto. Fix it to make sure the data can be transferred.
  4. The following line of code await client.UpdateDigitalTwinAsync(deviceId, updateTwinData); is used to update the corresponding digital Twin that matches the digital twin with the deviceId. Note that the deviceId can be different from your Azure IoTHub device ID. Make sure you set the same device ID in your code to the value which you have used for --twin-id property while creation using a similar statement like this az dt twin create --dt-name &lt;instance-hostname-or-name&gt; --dtmi &quot;dtmi:contosocom:DigitalTwins:Thermostat;1&quot; --twin-id thermostat67 --properties &#39;{&quot;Temperature&quot;: 0.0}&#39;

If you are using a Python SDK, you can formulate the message structure as follows to make sure the telemetry data sent is in JSON format.

MSG_TXT = &#39;{{&quot;temperature&quot;: {temperature},&quot;humidity&quot;: {humidity}, &quot;timesent&quot;: {timesent}}}&#39;
temperature = TEMPERATURE + (random.random() * 15)
humidity = HUMIDITY + (random.random() * 20)
x = datetime.now().isoformat()
timesent = dumps(datetime.now(), default=json_serial)
msg_txt_formatted = MSG_TXT.format(
temperature=temperature, humidity=humidity, timesent=timesent)
message = Message(msg_txt_formatted, content_encoding=&quot;utf-8&quot;, content_type=&quot;application/json&quot;)
client.send_message(message)

Once you have addressed all there parameters, you should push the data to Azure Digital Twin without any issues. Please refer the below image showing the data received on Azure Digital Twin using the same piece of code.
如何从IoT Hub获取遥测数据并传输到Azure数字孪生。

Please also refer to the thread Telemetry Data from IOT hub not pushing to azure function and not reflecting to Digital Twin? where a similar issue has been discussed.

答案2

得分: 0

我已更改此代码行,现在一切正常。

var cred = new DefaultAzureCredential();
var client = new DigitalTwinsClient(new Uri(adtServiceUrl), cred);

英文:

I have changed this code line and now everything works fine.

var cred = new DefaultAzureCredential();
var client = new DigitalTwinsClient(new Uri(adtServiceUrl), cred);

huangapple
  • 本文由 发表于 2023年5月17日 17:52:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270779.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定