I have an IoT Edge Module filtermodule which sends telemetry using send_message
(docs) with IoTHubModuleClient
every minute.
When I run this module, the IoT Hub message counter in the portal is incrementing. Also, I used this route in the IoT Edge Hub configuration for deployment:
"routes": {
"filtermoduleToIoTHub": "FROM /messages/modules/filtermodule/outputs/* INTO $upstream"
}
Furthermore, I created a custom route and endpoint in IoT Hub which routes messages to a storage account (key based authentication). The route query is true
and I tested the same telemetry data with the route and all tests pass in the sense that it matches the query.
Somehow the data is not ending up in the storage account and there is not really a straight forward way to debug why that is the case. Before I was using IoTHubDeviceClient
with send_message
(no IoT Edge) with the same route and storage account and data did actually show up in the storage account. What is missing here? I find the docs on IoT Edge and IoT Hub and how they work together quite confusing sometimes.
EDIT:
The telemetry data I send has the following format (the same format as when it worked previously):
{"Measurements": [{"Temperature": 20.5}, {"Temperature": 20.5}]}
I am using Terraform for deployment and this endpoint and route used to work:
# IoT Hub endpoint for bronze ingestion storage container
resource "azurerm_iothub_endpoint_storage_container" "bronze_ingestion_endpoint" {
resource_group_name = azurerm_resource_group.this.name
iothub_id = azurerm_iothub.this.id
name = "bronze-ingestion"
container_name = azurerm_storage_container.bronze_ingestion_avro.name
connection_string = azurerm_storage_account.bronze.primary_connection_string
file_name_format = "{iothub}/{YYYY}/{MM}/{DD}/{HH}/{mm}_{partition}.avro"
batch_frequency_in_seconds = 600
max_chunk_size_in_bytes = 10485760
encoding = "Avro"
}
# IoT Hub route for bronze ingestion storage container
resource "azurerm_iothub_route" "bronze_ingestion_route" {
resource_group_name = azurerm_resource_group.this.name
iothub_name = azurerm_iothub.this.name
name = "bronze-ingestion-route"
source = "DeviceMessages"
condition = "true"
endpoint_names = [azurerm_iothub_endpoint_storage_container.bronze_ingestion_endpoint.name]
enabled = true
}
EDIT 2:
I can confirm that if I use IoTHubModuleClient.create_from_connection_string(conn_string)
on my local machine, the route works and data shows up in the storage account. When I use IoTHubModuleClient.create_from_edge_environment()
on the IoT device within the edge environment, the route does not work (but the message counter in the portal increments).
The same is true for Azure IoT Explorer. I can monitor incoming events from if I use IoTHubModuleClient.create_from_connection_string(conn_string)
on my local machine, but nothing shows up If I use IoTHubModuleClient.create_from_edge_environment()
on the IoT device.
2
Answers
Apparently when you use
/messages/modules/filtermodule/outputs/*
you have to usesend_message_to_output
instead ofsend_message
(documentation). I assumed that usingsend_message
would send to any output, but that is not the case (documentation).send_message
does work if you use/messages/modules/*
,/messages/modules/<moduleId>/*
,/messages/*
or/*
.Below are the steps to send device data to Azure Storage using IoT Hub message routing:
From edge environment:
Create a azure Storage and Container . Connect Endpoint for an IoT Hub Using a Connection String.
Create a route using the following command:
Run the send message code. Refer to this link for the send message code.
Now, you can send device data to Azure Storage using IoT Hub message routing.