Отправка событий в Azure IoT Hub в сочетании с режимом глубокого сна

Я использую микроконтроллер Node ESP8266. У меня есть работающее приложение на C, которое постоянно отправляет данные датчиков температуры и влажности в Azure IoT Hub. Я вижу, как в Azure поступают события и сообщения.

Теперь я хочу, чтобы приложение отправляло данные примерно раз в минуту. Поэтому я реализовал сценарий глубокого сна. Проблема в том, что мои сообщения ставятся в очередь, но не отправляются.

Я подозреваю, что IoTHubClient_LL_DoWork() не отправляет данные непосредственно перед переходом устройства в режим глубокого сна. Но я недостаточно хорошо разбираюсь в языке C и AzureIoT SDK. Вот мой код:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiUdp.h>

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>

#include <AzureIoTHub.h>
#include <AzureIoTProtocol_MQTT.h>

#include <ArduinoJson.h>


#define IOT_CONFIG_CONNECTION_STRING "CONNSTRING"

#define DEVICE_ID "NodeMcu"

#define WIFI_SSID "SSID"
#define WIFI_PW "PW"

#define MESSAGE_MAX_LEN 256

static bool messagePending = false;
static bool messageSending = true;

static int messageCount = 1;

static IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle;

void setup()
{
    delay(1000);

    Serial.begin(115200);

    connect();
    initTime();

    iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(IOT_CONFIG_CONNECTION_STRING, MQTT_Protocol);
    if (iotHubClientHandle == NULL)
    {
        Serial.println("Failed on IoTHubClient_CreateFromConnectionString.");
        while (1);
    }

    //IoTHubClient_LL_SetOption(iotHubClientHandle, "product_info", "HappyPath_AdafruitFeatherHuzzah-C");
    //IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, receiveMessageCallback, NULL);
    //IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientHandle, deviceMethodCallback, NULL);
    //IoTHubClient_LL_SetDeviceTwinCallback(iotHubClientHandle, twinCallback, NULL);
}

void loop()
{
    if (!messagePending && messageSending)
    {
        char messagePayload[MESSAGE_MAX_LEN];
        readMessage(messageCount, messagePayload);
        sendMessage(iotHubClientHandle, messagePayload);
        messageCount++;
        delay(5000);
    }

    IoTHubClient_LL_DoWork(iotHubClientHandle);
    delay(10);
}

void connect()
{
    delay(10);

    if (WiFi.status() == WL_CONNECTED)
    {
        Serial.println("Already connected...");
        return;
    }

    // Connect to WiFi network
    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(WIFI_SSID);

    WiFi.begin(WIFI_SSID, WIFI_PW);

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
}

void initTime() {
    time_t epochTime;

    configTime(0, 0, "pool.ntp.org", "time.nist.gov");

    while (true) {
        epochTime = time(NULL);

        if (epochTime == 0) {
            Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry.");
            delay(2000);
        } else {
            Serial.print("Fetched NTP epoch time is: ");
            Serial.println(epochTime);
            break;
        }
    }
}

void readMessage(int messageId, char *payload)
{
    float temperature = readTemperature();
    float humidity = readHumidity();
    StaticJsonBuffer<MESSAGE_MAX_LEN> jsonBuffer;
    JsonObject &root = jsonBuffer.createObject();
    root["deviceId"] = DEVICE_ID;
    root["messageId"] = messageId;

    // NAN is not the valid json, change it to NULL
    if (std::isnan(temperature))
    {
        root["temperature"] = NULL;
    }
    else
    {
        root["temperature"] = temperature;
    }

    if (std::isnan(humidity))
    {
        root["humidity"] = NULL;
    }
    else
    {
        root["humidity"] = humidity;
    }

    root.printTo(payload, MESSAGE_MAX_LEN);
}

float readTemperature()
{
    return random(20, 30);
}

float readHumidity()
{
    return random(30, 40);
}

static void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, char *buffer)
{
    IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char *)buffer, strlen(buffer));
    if (messageHandle == NULL)
    {
        Serial.println("Unable to create a new IoTHubMessage.");
    }
    else
    {
        //MAP_HANDLE properties = IoTHubMessage_Properties(messageHandle);
        //Map_Add(properties, "temperatureAlert", temperatureAlert ? "true" : "false");
        Serial.printf("Sending message: %s.\r\n", buffer);
        if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, NULL) != IOTHUB_CLIENT_OK)
        {
            Serial.println("Failed to hand over the message to IoTHubClient.");
        }
        else
        {
            messagePending = true;
            Serial.println("IoTHubClient accepted the message for delivery.");
        }

        IoTHubMessage_Destroy(messageHandle);
    }
}

static void sendCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void *userContextCallback)
{
    if (IOTHUB_CLIENT_CONFIRMATION_OK == result)
    {
        Serial.println("Message sent to Azure IoT Hub");
    }
    else
    {
        Serial.println("Failed to send message to Azure IoT Hub");
    }
    messagePending = false;
}

, 👍0


1 ответ


Лучший ответ:

2

Вам необходимо вызывать IoTHubClient_LL_DoWork до тех пор, пока все сообщения не будут обработаны, и только после этого вы можете перейти в спящий режим.

Проверьте следующий код:

void IoTHubFullSendReceive() 
{
  IOTHUB_CLIENT_STATUS Status;

  while ((IoTHubClient_LL_GetSendStatus(IoTHubClientHandle, &Status) == IOTHUB_CLIENT_OK) && (Status == IOTHUB_CLIENT_SEND_STATUS_BUSY))
  {
      IoTHubClient_LL_DoWork(IoTHubClientHandle);
      ThreadAPI_Sleep(50);
  }
}
,