0

I am still pretty new to digital twins/IoT and am currently working on a digital twin solution using simulated data from the IoT Hub VS Code extension. I can successfully send the simulated telemetry data to my IoT Hub however when I try to forward it onto my ADT instance using a Function file it is not being received.

However I can see that the messages are being received in ADT and being executed in my function file while I run the code. However when I update my query in ADT it is not picking up these messages and displaying them within the explorer.

Any help will be greatly appreciated as I have hit a bit of a wall with it today!

From my thoughts there are 3 possible causes that might stop it from receiving the telemetry data.

The Azure Function code - I have checked this over a couple times and have even checked with chat gpt to ensure this is correct.

The DTDL model in ADT - I based this off of the working version of a twin I made before using a virtual raspberry pi and just added the simulated data sources which I was including.

The Event Grid - Not 100% sure about this being the cause as from what I know of the process however I did the exact same set up as I did with my previous working project.

I have tried setting up again in a new environment as well as changing the DTDL and Function file however that did not seem to change anything.

Here is the code used in my simulated device (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);

Here is the code from my Azure Function File (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}");
            }
        }
    }
}
Craig BH
  • 1
  • 1
  • please share your code – Sampath Jul 12 '23 at 14:12
  • @Sampath Just added the code to my post. – Craig BH Jul 13 '23 at 08:58
  • Refer how to ingest device telemetry messages from Azure IoT Hub to digital twins in an instance of [Azure Digital Twins](https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/digital-twins/how-to-ingest-iot-hub-data.md). – Sampath Jul 13 '23 at 11:27
  • in the first code, you are sending telemetry data to the Azure IoT hub and the code is to Ingest IoT Hub telemetry into Azure Digital Twins.right? – Sampath Jul 14 '23 at 03:24
  • Refer this for Ingest IoT Hub telemetry into [Azure Digital Twins](https://learn.microsoft.com/en-us/azure/digital-twins/how-to-ingest-iot-hub-data) – Sampath Jul 14 '23 at 03:25
  • will give a sample of how to send telemetry messages from Azure IoT Hub and a reference to how to ingest IoT Hub telemetry into Azure Digital Twins. – Sampath Jul 14 '23 at 05:28

1 Answers1

0
const  {  Client,  Message  } = require('azure-iot-device');

const  connectionString = 'HostName=sampath567.azure-devices.net;DeviceId=sampathy123;SharedAccessKey';
const  client = Client.fromConnectionString(connectionString,  require('azure-iot-device-mqtt').Mqtt);
function  generateTemperature()  {
return  Math.floor(Math.random() * 100);
}
function  sendTelemetry()  {
const  temperature = generateTemperature();
const  data = JSON.stringify({  temperature  });
const  message = new  Message(data);
message.properties.add('temperatureAlert', (temperature > 70) ? 'true' : 'false');
console.log(`Sending telemetry: ${data}`);
client.sendEvent(message,  (err)  =>  {
if (err) {
console.error(`Error sending telemetry: ${err.toString()}`);
}  else  {
console.log('Telemetry sent successfully');
}
});
}
client.open((err)  =>  {
if (err) {
console.error(`Error opening IoT Hub connection: ${err.toString()}`);
}  else  {
console.log('IoT Hub connection established');
setInterval(sendTelemetry,  5000);
}
});

enter image description here

enter image description here

Second Part:

enter image description here

Sampath
  • 810
  • 2
  • 2
  • 13