Azure / azure-iot-explorer

Cross-platform UI for interacting with devices attached to Azure IoT Hub. This tool is meant for learning and testing, not for production environment.
MIT License
223 stars 74 forks source link

[Help request] Resolve model definition from local folder <-- **Can't get this to work for Telemetry.** #468

Closed djaus2 closed 2 years ago

djaus2 commented 3 years ago

Describe the bug ✔️ Resolve model definition from local folder <-- Can't get this to work for Telemetry. ✔️ Resolve model definition from model repo ✔️ Resolve public model repo ✔️ Resolve from configurable model repo ❌ Resolve custom repo 🚫 Resolve from connected device is no longer supported ✔️ Configure the order to resolve models

To Reproduce Steps to reproduce the behavior:

  1. Running a PnPBridge with the Arduino Sample. Using scha from local folder.
  2. Can exercise Model Property Updates and Commands and general Telemetry
  3. But the Model Telemetry does return any output

Expected behavior Expect to see the same or similar Telemetry .in the Model mode as per the "general Telemetry. When change to use Model expect to see that parsed into the model

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Is there some "magic" nexus between the config.json and the schema.json for the telemetry that is needed for the modelling of the received telemetry data type to work?

djaus2 commented 3 years ago

The schema file:


{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:contoso:serialpnp;1",
  "@type": "Interface",
  "displayName": "Pnp Bridge Root Interface Model serialpnp",
  "description": "Arduino Serial PnP",
  "comment": "Serial PnP for Arduino",

  "contents": [
    {
      "@type": "Property",
      "displayName": "Sample Rate",
      "description": "Rate of temperature readings.",
      "name": "sample_rate",
      "schema": "integer",
      "writable": true
    },
    {
      "@type": [
      "Telemetry",
      "Temperature"
      ],
      "description": "Current temperature on the device",
      "displayName": "Temperature",
      "name": "temperature",
      "schema": "double",
      "unit": "degreeCelsius"
    },
    {
      "@type": "Command",
      "name": "calibrate",
      "description": "Calibrates the thermometer.",
      "commandType": "synchronous",
      "request": {
          "name": "input",
          "schema": "integer"
      },
      "response": {
        "name": "calibrateResponse",
        "schema": "integer"
      }  
    },
    {
      "@type": "Command",
      "name": "calibration",
      "comment": "Enable-disable sampling.",
      "commandType": "synchronous" ,
      "request": {
        "name": "input",
        "schema": "integer"
      },
      "response": {
        "name": "output",
        "schema": "integer"
      }  
    },
    {
      "@type": "Command",
      "name": "toggle_state",
      "comment": "Enable-disable sampling.",
      "commandType": "synchronous" ,
      "request": {
        "name": "input",
        "schema": "integer"
      },
      "response": {
        "name": "output",
        "schema": "integer"
      }  
    }
  ]

}
djaus2 commented 3 years ago

The config.json file Note that the schema reference at the top is to the schema as above, in a local folder.

{

    "$schema": "../../../../../../../../.././iot-plug-and-play-bridge/pnpbridge/docs/schemas/grovearduinoserialpnpModel.json",
    "pnp_bridge_connection_parameters": 
    {
        "connection_type" : "connection_string",
        "connection_string" : "HostName=HubPnP3.azure-devices.net;DeviceId=PnPDev3",
        "root_interface_model_id": "dtmi:com:contoso:serialpnp;1",
        "auth_parameters": 
        {
            "auth_type": "symmetric_key",
            "symmetric_key": "q+6OU6byhvpT9zU3Mbr6KhR8Ur47zEa/EFyM8fEHHMU="
        }
    },
    "pnp_bridge_debug_trace": false,
    "pnp_bridge_config_source": "local",
    "pnp_bridge_interface_components": 
    [
        {
            "pnp_bridge_component_name": "serialpnp",
            "pnp_bridge_adapter_id": "serial-pnp-interface",
            "pnp_bridge_adapter_config": 
            {
                "com_port": "COM4",
                "_comment": "NOTE: com_port parameter will NOT be used when use_com_device_interface is set to true. In case of windows iot edition, the COMXX symbolic links are not created. Setting use_com_device_interface to false will pick the first available COM interface.",
                "use_com_device_interface": "false",
                "baud_rate": "115200"
            }
        }
    ]
}
djaus2 commented 3 years ago

Note at start do get the following in the _IoT Plug and Play components->DEFAULTCOMPONENT->Telemetry .. when Model is not enabled

Fri Sep 10 2021 23:17:26 GMT+1000 (Australian Eastern Standard Time):
{
  "body": {
    "0": 123,
    "1": 34,
    "2": 77,
    "3": 111,
    "4": 100,
    "5": 117,
    "6": 108,
    "7": 101,
    "8": 83,
    "9": 116,
    "10": 97,
    "11": 116,
    "12": 101,
    "13": 34,
    "14": 58,
    "15": 80,
    "16": 110,
    "17": 112,
    "18": 66,
    "19": 114,
    "20": 105,
    "21": 100,
    "22": 103,
    "23": 101,
    "24": 32,
    "25": 99,
    "26": 111,
    "27": 110,
    "28": 102,
    "29": 105,
    "30": 103,
    "31": 117,
    "32": 114,
    "33": 97,
    "34": 116,
    "35": 105,
    "36": 111,
    "37": 110,
    "38": 32,
    "39": 99,
    "40": 111,
    "41": 109,
    "42": 112,
    "43": 108,
    "44": 101,
    "45": 116,
    "46": 101,
    "47": 125
  },
  "enqueuedTime": "Fri Sep 10 2021 23:17:26 GMT+1000 (Australian Eastern Standard Time)",
  "properties": {}
}

But get garbage when it tries to parse it into the model such as:

{ "0": 123 }
This telemetry '0' is not in the model. You may consider modeling it.
djaus2 commented 3 years ago

That message above reads {"Modulestate":PnpBridge complete}

rido-min commented 3 years ago

Hi @djaus2

I'd suggest to report pnp bridge related issues to https://github.com/Azure/iot-plug-and-play-bridge

Regarding IoT Explorer, can you try to reproduce your issue without the pnp bridge? Based on the title, it's not clear what is not working, can you clarify?

djaus2 commented 3 years ago

I have also posted an Issue on the Bridge.

My question here, may be this should have been a request for help, rather than a bug, ... Given that the raw telemetry Payload (from Menu->Telemetry, not from the Menu->IoT Plug and Play components tab->Telemetry) appears to be correct, why can't the Azure IoT Explorer get it the model view and interpret/parse it? The IoT Explorer does receive the raw Telemetry, just not in the Model context. The model does work for properties and commands but not the Telemetry, The "raw" Telemetry:

{
  "body": {
    "temperature": 12.34
  },
  "enqueuedTime": "Sat Sep 11 2021 15:04:04 GMT+1000 (Australian Eastern Standard Time)",
  "properties": {}
}

I suspect something is incorrect with the schema, at this end.

YingXue commented 2 years ago

Hi @djaus2 You may want to check the system property of the temeletry and see if that contains the interface id. The field that we are specifically looking for is 'dt-dataschema'

djaus2 commented 2 years ago

First few lines are:

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:contoso:serialpnp;1",
  "@type": "Interface",

Suggestions ??

rido-min commented 2 years ago

Hi @djaus2

Can you confirm if IoTExplorer is able to find the DTDL interface from your configured local folder?

In the IoT Plug and Play tab you can see if the model have been found in any of your configured sources

djaus2 commented 2 years ago

Thx @rido-min As indicated, in IoTExplorer, it finds the model and I can see Device twinning, get/set Properties and send Commands. I can't in the property context read Telemetry. I can though in IoTExplorer read the raw Telemetry in the non PnP Modsel context..

rido-min commented 2 years ago

Hi @djaus2

The telemetry messages you shared seems like a byte array rather than a UTF8 Json string. How is that telemetry produced? which SDK/Library are you using? We usually recommend to set the content type and application message properties in the message.

djaus2 commented 2 years ago

Hi @rido-min

Here is my Telemetry sending code:

            DeviceClient deviceClient;
        TransportType s_transportType = TransportType.Mqtt;
            var messageString = JsonConvert.SerializeObject(Sensor);
            var message = new Message(Encoding.ASCII.GetBytes(messageString));
            deviceClient = DeviceClient.CreateFromConnectionString(s_connectionString, s_transportType);
        deviceClient.SendEventAsync(message);

I am using the following: "Microsoft.Azure.Devices.Client" Version="1.33.1"

Its a .NET 5 C# Console app.

Q. Do I need to set message.ContentType to something specific? Or the Schema and/or the ContentEncoding?

djaus2 commented 2 years ago

image Here are the message properties at runtime just before sending.

rido-min commented 2 years ago

yes, from the samples:

using var message = new Message(Encoding.UTF8.GetBytes(telemetryPayload))
{
    ContentEncoding = "utf-8",
    ContentType = "application/json",
};
djaus2 commented 2 years ago

Thx @rido-min

My code is now:

            var messageString = JsonConvert.SerializeObject(Sensor);
            var message = new Message(Encoding.UTF8.GetBytes(messageString))
            {
                ContentEncoding = "utf-8",
                ContentType = "application/json"
            };
            await deviceClient.SendEventAsync(message);

And message properties just prior to sending are now: image

Still not getting PnP Telemetry.

Raw Telemetry is

{
  "body": {
    "No": 0,
    "Id": "6513d5ed-c0f2-4346-b3fa-642c48fd66a5",
    "Value": -1,
    "environ": null,
    "State": false,
    "Values": null,
    "SensorType": 0,
    "TimeStamp": 637717963322345700,
    "DateTime": "6/11/2021 \t11:52:12 AM"
  },
  "enqueuedTime": "Sat Nov 06 2021 11:52:18 GMT+1100 (Australian Eastern Daylight Time)",
  "properties": {},
  "systemProperties": {
    "iothub-connection-device-id": "PnPDev4",
    "iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
    "iothub-connection-auth-generation-id": "637673059174207434",
    "iothub-enqueuedtime": 1636159938774,
    "iothub-message-source": "Telemetry",
    "x-opt-sequence-number": 11854,
    "x-opt-offset": "30064930928",
    "x-opt-enqueued-time": 1636159938765
  }
}
YingXue commented 2 years ago

Hi, As mentioned in my earlier reply, i don't see 'dt-dataschema' in the system properties, and this it why the telemetry does not show up under pnp.

djaus2 commented 2 years ago

@YingXue Thanks for the follow up. Can you indicate how/where to include that?

YingXue commented 2 years ago

Hi @djaus2 I am afraid I am not an expert here. I have been using the Node sdk for pnp devices which is injecting the system property for me automatically. Please refer to this doc I've found which mentioned this property: https://docs.microsoft.com/en-us/azure/iot-develop/concepts-convention#telemetry