user39524: I use a Node MCU ESP8266. I have a working C app sending temperature and humidity sensor data to Azure IoT Hub continuously. I see events/messages coming in at Azure.
Now I'd like the app to only send data every minute or so. So I implemented a deep sleep scenario. The problem is my messages are queued but not sent.
My suspicion is that the IoTHubClient_LL_DoWork() does not send the data immediately before the device is going into deep sleep. But I don't know enough about C or the AzureIoT SDK. Here is my code:
#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;
}


user45874: You need to call IoTHubClient_LL_DoWork until all messages are processed and only after that you can go to sleep.
Check the following code:
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);
  }
}


39524: <p>I use a Node MCU ESP8266. I have a working C app sending temperature and humidity sensor data to Azure IoT Hub continuously. I see events/messages coming in at Azure.</p>

<p>Now I'd like the app to only send data every minute or so. So I implemented a deep sleep scenario. The problem is my messages are queued but not sent.</p>

<p>My suspicion is that the IoTHubClient_LL_DoWork() does not send the data immediately before the device is going into deep sleep. But I don't know enough about C or the AzureIoT SDK. Here is my code:</p>

<pre><code>#include &lt;ESP8266WiFi.h&gt;
#include &lt;WiFiClientSecure.h&gt;
#include &lt;WiFiUdp.h&gt;

#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdint.h&gt;
#include &lt;time.h&gt;
#include &lt;sys/time.h&gt;

#include &lt;AzureIoTHub.h&gt;
#include &lt;AzureIoTProtocol_MQTT.h&gt;

#include &lt;ArduinoJson.h&gt;


#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 &amp;&amp; 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&lt;MESSAGE_MAX_LEN&gt; jsonBuffer;
    JsonObject &amp;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;
}
</code></pre>
 45874: <p>You need to call IoTHubClient_LL_DoWork until all messages are processed and only after that you can go to sleep.</p>

<p>Check the following code:</p>

<pre><code>void IoTHubFullSendReceive() 
{
  IOTHUB_CLIENT_STATUS Status;

  while ((IoTHubClient_LL_GetSendStatus(IoTHubClientHandle, &amp;Status) == IOTHUB_CLIENT_OK) &amp;&amp; (Status == IOTHUB_CLIENT_SEND_STATUS_BUSY))
  {
      IoTHubClient_LL_DoWork(IoTHubClientHandle);
      ThreadAPI_Sleep(50);
  }
}
</code></pre>
