You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32S3基于ESP-IDF发送遥测数据至Azure IoT Hub无法路由至CosmosDB

解决方案:ESP32S3 PNP设备Azure IoT路由到CosmosDB失效及字段过滤问题

一、修复路由不生效问题(针对PNP消息的特殊处理)

你遇到的问题大概率是PNP遥测消息的格式或属性设置方式和普通非PNP消息不同导致的,以下是具体修正步骤:

  1. 严格匹配IoT Hub要求的属性键名
    IoT Hub对消息属性键名大小写敏感,必须使用content-type和content-encoding(全小写),不能用驼峰式的contentType或contentEncoding。在sample_azure_iot_pnp.c的遥测发送逻辑里,通过AzureIoTMessage_SetProperty函数正确添加:
AzureIoTMessageHandle_t xMessage = AzureIoTPnP_CreateTelemetryMessage(xPnpDeviceHandle, "telemetryComponentName", "telemetryName");
// 正确设置消息属性
AzureIoTMessage_SetProperty(xMessage, "content-type", "application/json");
AzureIoTMessage_SetProperty(xMessage, "content-encoding", "utf-8");
// 设置遥测 payload
AzureIoTMessage_SetPayload(xMessage, cPayload, strlen(cPayload));
// 发送消息
AzureIoTPnP_SendTelemetry(xPnpDeviceHandle, xMessage, NULL);
AzureIoTMessage_Destroy(xMessage);

注意:如果是默认组件,AzureIoTPnP_CreateTelemetryMessage的第二个参数传NULL即可。

  1. 检查PNP遥测的payload结构是否匹配路由查询
    PNP遥测的payload默认会包含组件嵌套结构,比如非默认组件的遥测payload格式为{"<componentName>": {"<telemetryName>": <value>}}。如果你的路由查询直接用action = "xxx",但实际action嵌套在组件对象里,路由会匹配失败。
    举个例子:
  • 实际PNP payload:{"sensor": {"temperature": 25, "action": "read"}}
  • 错误路由查询:action = "read"
  • 正确路由查询:$body.sensor.action = "read"

你可以在Azure IoT Explorer里查看原始消息,确认payload实际结构后调整查询语句。

  1. 验证消息属性是否正确携带
    在Azure IoT Explorer的消息详情里,查看Application Properties,确认content-type和content-encoding已附加。如果没有,检查代码中消息创建、属性设置、发送的顺序(必须先设属性再发送,发送后无法修改)。

二、用消息属性实现路由,避免action字段存入CosmosDB

要让action仅用于路由判断、不进入CosmosDB,只需把action从payload移到消息的应用属性中:

  1. 修改设备端代码,将action作为消息属性发送
AzureIoTMessageHandle_t xMessage = AzureIoTPnP_CreateTelemetryMessage(xPnpDeviceHandle, NULL, "temperature");
// 设置必要的内容属性
AzureIoTMessage_SetProperty(xMessage, "content-type", "application/json");
AzureIoTMessage_SetProperty(xMessage, "content-encoding", "utf-8");
// 添加action作为应用属性
AzureIoTMessage_SetProperty(xMessage, "action", "read");
// 设置payload(仅包含需存入CosmosDB的字段)
const char* cPayload = "{\"temperature\": 25}";
AzureIoTMessage_SetPayload(xMessage, cPayload, strlen(cPayload));
// 发送消息
AzureIoTPnP_SendTelemetry(xPnpDeviceHandle, xMessage, NULL);
AzureIoTMessage_Destroy(xMessage);
  1. 调整路由规则的查询条件
    路由查询直接引用属性,不再依赖payload:
properties.action = "read"
  1. 确认CosmosDB存储内容
    默认情况下,CosmosDB只会存储payload内容,action作为消息属性不会被写入(除非你在路由设置里特意配置要包含属性)。

三、额外排查点

  • 检查IoT Hub路由规则是否启用,CosmosDB的连接字符串、容器配置是否正确(比如分区键是否匹配路由设置)。
  • 查看IoT Hub的「监控」->「路由日志」,里面会记录路由匹配失败的具体原因(如消息格式错误、查询不匹配等),是定位问题的关键。

内容的提问来源于stack exchange,提问作者Adrian Wreyford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 12:10:31