I would like to send the telemetry data from the IOT hub to Azure digital twins using Python instead of C#( I don't have experience with C#), but I can't get it.
I have followed the complete example from Microsoft (https://learn.microsoft.com/en-us/azure/digital-twins/how-to-ingest-iot-hub-data) without success.
This is my code for Simulated Device. I checked and it successfully send the message to IoT Hub:
from azure.iot.device import IoTHubDeviceClient
import json
import random
import time
CONNECTION_STRING = "<DeviceIDConnectionString>"
def simulate_telemetry(device_client):
while True:
temperature = random.randint(20, 30)
humidity = random.randint(60, 80)
telemetry = {
"temperature": temperature,
"humidity": humidity
}
message = json.dumps(telemetry)
device_client.send_message(message)
print(f"Sent message: {message}")
time.sleep(1)
if __name__ == "__main__":
device_client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)
device_client.connect()
simulate_telemetry(device_client)
And this is the code for function app using python and event grid trigger ( I followed the C# code in the tutorial link):
import os
import logging
import json
from azure.identity import DefaultAzureCredential
from azure.digitaltwins.core import DigitalTwinsClient
from azure.core.exceptions import ResourceNotFoundError
import azure.functions as func
adt_instance_url = os.getenv("DIGITAL_TWINS_URL")
if adt_instance_url is None:
logging.error("Application setting 'DIGITAL_TWINS_URL' not set")
async def main(event: func.EventGridEvent):
try:
# Authenticate with Digital Twins
credential = DefaultAzureCredential()
client = DigitalTwinsClient(adt_instance_url, credential)
logging.info("ADT service client connection created.")
if event is not None and event.data is not None:
logging.info(event.data)
# Find device ID and temperature
device_message = event.get_json()
device_id = device_message["systemProperties"]["iothub-connection-device-id"]
temperature = device_message["body"]["temperature"]
humidity = device_message["body"]["humidity"]
logging.info(f"Device: {device_id} Temperature is: {temperature} Humidity is : {humidity}")
# Update twin with device temperature
twin_id = device_id
patch = [
{
"op": "replace",
"path": "/Temperature",
"value": temperature
},
{
"op": "replace",
"path": "/Humidity",
"value": humidity
}
]
await client.update_digital_twin(twin_id, patch)
except ResourceNotFoundError:
logging.error(f"Digital twin with ID {twin_id} not found.")
except Exception as ex:
logging.error(f"Error in ingest function: {ex}")
I also create the event subscription to connect IoT hub and Function App already. I follow all the step in tutorial.
When I run the function app locally on VS code ( Ubuntu 20.04), it executed successfully but have this error in between:
Error in ingest function: 'NoneType' object has no attribute 'startswith'
I only use these 2 files code for whole project.
I run the query on Azure Digital Twins explorer but I don't see the twin updated as expected.
Should I add something else (code) or what can I change? I think maybe the problem is missing the Digital Twins as output or IoT Hub as input.