【问题标题】:Publishing JSON object through MQTT to AWS IoT from ESP32 using C and ESP-IDF framework使用 C 和 ESP-IDF 框架通过 MQTT 将 JSON 对象从 ESP32 发布到 AWS IoT
【发布时间】:2020-09-18 13:00:43
【问题描述】:

我有一个结构 IoT_Publish_Message_Params 需要准备,以便准备在 AWS IoT 上发布。当我将字符串作为有效负载传递时,下面的 sn-p 工作得很好。

/**
 * @brief Publish Message Parameters Type
 *
 * Defines a type for MQTT Publish messages. Used for both incoming and out going messages
 *
 */
typedef struct {
    QoS qos;        ///< Message Quality of Service
    uint8_t isRetained; ///< Retained messages are \b NOT supported by the AWS IoT Service at the time of this SDK release.
    uint8_t isDup;      ///< Is this message a duplicate QoS > 0 message?  Handled automatically by the MQTT client.
    uint16_t id;        ///< Message sequence identifier.  Handled automatically by the MQTT client.
    void *payload;      ///< Pointer to MQTT message payload (bytes).
    size_t payloadLen;  ///< Length of MQTT payload.
} IoT_Publish_Message_Params;

IoT_Publish_Message_Params paramsQOS0;
sprintf(cPayload, "%s : %d ", "Hello from HOME!!", i);

paramsQOS0.qos = QOS0;
paramsQOS0.payload = (void *) cPayload;
paramsQOS0.isRetained = 0;
paramsQOS0.payloadLen = strlen(cPayload);
rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, &paramsQOS0);

现在我想发送一个实际的 JSON 有效负载,但我不知道该怎么做。我尝试使用 cJSON 创建 JSON 对象:

cJSON *root,*fmt;
root=cJSON_CreateObject();
paramsQOS0.payload = (void *) root
cJSON_AddItemToObject(root, "response", fmt=cJSON_CreateObject());
cJSON_AddNumberToObject(fmt,"hello", 123);
cJSON_AddNumberToObject(fmt,"bye", 321);

但是,我的问题是,我在这里传递什么作为 IoT_Publish_Message_Params.payloadLen ?以及如何将 json 对象传递给 IoT_Publish_Message_Params.payload?

【问题讨论】:

  • 如果你不会有很多动态消息并且如果你在 lambda 或后端服务中处理你的消息,我建议你发送它二进制。对于像 ESP32 这样的低内存嵌入式系统,处理 json 可能会导致内存效率低下。但是您应该在 IoT 规则级别对消息进行编码,例如“选择编码(*)作为来自 /some/topic 的数据”

标签: c mqtt esp32 aws-iot cjson


【解决方案1】:

在我看来,您有两个选择。将 JSON 作为字符串或原始字节发送。

如果您想将其作为字符串发送(例如{"CarType":"BMW","carID":"bmw123"}),那么您想将其转换为字符串。找到了一些代码here

char* str = cJSON_Print(root);  
paramsQOS0.payload = (void *) str;
paramsQOS0.payloadLen = strlen(str);

但是,将其作为原始字节发送会更有效。为此,您需要一个指向对象开头的指针,以及对象的大小(以字节为单位)。快速扫描GitHub Page 我发现cJSON_GetArraySize 显然返回了对象大小。

那么它应该看起来像这样:

paramsQOS0.payload = (void *) root;
paramsQOS0.payloadLen = cJSON_GetArraySize(root); // Not sure about this one

免责声明,我没有使用过 cJSON,也没有测试过代码。我正试图告诉你该往哪个方向走。

【讨论】:

    【解决方案2】:

    IoT_Publish_Message_Params 具有 payloadpayloadLen 成员,因此您可以提供任何有效的内存和要发送的字节长度。在您的第一个示例中,您提供了一个静态分配的字符串及其长度。

    JSON 是基于字符串的编码协议,因此payload 将是一个char 指针,payloadLen 可以使用strlen 计算。

    cJSON_Print返回一个对象的json字符串,使用它返回的指针,赋值给payload

    请阅读cJSON API documentation如何使用它。下面是如何使用修改代码来发送 JSON 字符串。

    IoT_Publish_Message_Params paramsQOS0;
    char *json_str;
    
    /* create a json message */
    cJSON *root, *response;
    root = cJSON_CreateObject();
    response = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "response", response);
    cJSON_AddNumberToObject(response, "hello", 123);
    cJSON_AddNumberToObject(response, "bye", 321);
    
    json_str = cJSON_Print(root);
    if (json_str != NULL)
    {
        paramsQOS0.qos = QOS0;
        paramsQOS0.isRetained = 0;
        paramsQOS0.payload = json_str;
        paramsQOS0.payloadLen = strlen(json_str);
        rc = aws_iot_mqtt_publish(&client, TOPIC, TOPIC_LEN, &paramsQOS0);
        free(json_str);
    }
    
    cJSON_Delete(root);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 2022-06-12
      • 2017-02-22
      • 1970-01-01
      • 2022-07-29
      • 2022-10-07
      • 2021-02-28
      • 2021-06-24
      相关资源
      最近更新 更多