Отправка событий в 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;
}
@j7nn7k, 👍0
1 ответ
Лучший ответ:
Вам необходимо вызывать 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);
}
}
- Как преобразовать полезную нагрузку byte* в строку
- Пиринговая коммуникация
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- ESP8266 глубокий сон и MQTT
- Как разобрать 20180810T143000Z в time_t
- Вывод ESP8266 из deepSleep с помощью кнопки
- PIR движение выводит ESP8266 из глубокого сна
- Память ESP8266 RTC (для загрузки)