ESP32, ArduinoJSON и MQTT: зависание в цепочке процессовC++

Программы на C++. Форум разработчиков
Ответить
Гость
 ESP32, ArduinoJSON и MQTT: зависание в цепочке процессов

Сообщение Гость »

Некоторое время у меня возникли проблемы с моим приложением, и я не могу понять, почему ESP32 застревает в цепочке обработки. Проблема случайно возникает через 3 или 4 недели в рабочем режиме. Иногда через 1 неделю. Трудно сказать.
Итак, сначала позвольте мне объяснить, как выглядит цепочка процессов.
При запуске ESP клиент MQTT (AsyncMQTT_Generic Library) ) подключается к MQTT-брокеру Mosquitto, подписывается на тему esp/config/, получает полезную нагрузку сообщения в виде объекта JSON
{"idsl":900000000,"dsle":true,"ihttp":1800000,"time":1712487701726,"addr":["C4:7C:8D:6D:31:2A"],"syse":true}

который десериализуется с помощью ArduinoJson (версия 6.21.5) и сохраняет его в хранилище RTC rtcConfig ESP32 следующим образом:
struct RtcData {
unsigned int wakeupCnt;
uint32_t channel;
uint8_t bssid[6];
uint8_t systemEnabled;
uint8_t deepSleepEnabled;
uint64_t deepSleepInterv;
uint32_t httpRequestInterv;
uint8_t hasConfig;
uint64_t time;
char bleAddr[MAX_BLE_NUMBER][MAC_ADDR_LENGTH];
};

// Real Time Clock memory
RTC_DATA_ATTR RtcData rtcConfig;

StaticJsonDocument jsonConfig;

// Receiving MQTT message from topic
void onMqttMessage(char* topic, char* payload, const AsyncMqttClientMessageProperties& properties,
const size_t& len, const size_t& index, const size_t& total) {

Serial.printf("MQTT received message on topic '%s'\n", topic);
Serial.printf(" QoS: %u", properties.qos);
Serial.printf(", dup: %d", properties.dup);
Serial.printf(", retain: %d", properties.retain);
Serial.printf(", len: %u", len);
Serial.printf(", index: %u", index);
Serial.printf(", total: %u\n", total);

if (strcmp(topic, topicConfigMac) == 0) {
deserializePayload(payload);
} else {
Serial.printf("MQTT received message topic %s is unequal to %s\n", topic, topicConfigMac);
enterSleepMode();
}
}

void deserializePayload(char* payload) {
Serial.print("Serialize payload: ");
jsonConfig.clear();
DeserializationError error = deserializeJson(jsonConfig, payload);

if (error) {
Serial.printf("failed: %s", error.c_str());
return;
} else {
size_t size = serializeJson(jsonConfig, Serial); // printing JSON to Serial for debugging
Serial.printf(", %u bytes\n", size);

// Returns false on initial boot as expected
// Should return true after storing configuration to RTC
if (isConfigUpToDate()) {
Serial.println("Configuration is up-to-date");
publishSensorData();
} else {
storePayloadToRtc(payload);
reboot = true;
mqttClient.disconnect();
// Rebooting ESP32; After reboot subscribe to topic again
// Now, we use the configuration stored in RTC storage
// isConfigUpToDate() should return true
}
}
}

bool isConfigUpToDate() {
// Is this a valid statement to compare a uint64_t with jsonConfig?
return rtcConfig.time > 0 && rtcConfig.time == (uint64_t)jsonConfig["time"];
}

void storePayloadToRtc(char* payload) {
Serial.println("Store payload to RTC");
rtcConfig.hasConfig = true;
rtcConfig.systemEnabled = jsonConfig["syse"];
rtcConfig.deepSleepEnabled = jsonConfig["dsle"];
rtcConfig.deepSleepInterv = jsonConfig["idsl"];
rtcConfig.httpRequestInterv = jsonConfig["ihttp"];
rtcConfig.time = (uint64_t)jsonConfig["time"];
// BLE addresses
JsonArray bleAddrArray = jsonConfig["addr"].as();
for (int i = 0; i < bleAddrArray.size(); i++) {
String addr = bleAddrArray.as();
strcpy(rtcConfig.bleAddr, addr.c_str());
rtcConfig.bleAddr[18] = '\0';
}
// fill up the rest of the array with \0
if (bleAddrArray.size() < MAX_BLE_NUMBER) {
memset(rtcConfig.bleAddr[bleAddrArray.size()], '\0', sizeof(rtcConfig.bleAddr));
}
}

Поскольку rtcConfig.time изначально равен 0, isConfigUpToDate() возвращает false и после этого сохраняет конфигурацию в RTC. После перезагрузки rtcConfig.time больше не равен 0 и должен публиковать данные датчика на сервере MQTT.
Из файлов журналов Mosquitto и анализов: Я могу сказать, что процесс застревает в вышеуказанном методе isConfigUpToDate(), который вернет false после первой ожидаемой перезагрузки. Но на данный момент я ожидаю истинности.
Теперь я не уверен, почему он там застревает. Причин может быть несколько:
Логично ли выражение
rtcConfig.time > 0 && rtcConfig.time == (uint64_t)jsonConfig["time"]

технически действителен в любое время?
Есть ли способ без отладки USB подтвердить, что полученное время атрибута JSON установлено как Я ожидаю, что так и будет?
К сожалению, я не могу устранить проблему через USB-порт в «производственном режиме», поскольку он питается от аккумулятора и солнечной панели. Если я отлаживаю его через USB-порт, проблема никогда не возникает, вероятно, потому, что у меня недостаточно терпения, чтобы дождаться неудачной итерации. Это происходит только через 3 или 4 недели в производственном режиме. Иногда через 1 неделю. Трудно сказать.
Любая идея или вклад приветствуются! Я сталкиваюсь с этой проблемой уже несколько месяцев и не могу от нее избавиться...
Заранее спасибо
РЕДАКТИРОВАТЬ >
Ниже приведен действительный журнал Mosquitto, в котором все работает нормально:
2024-04-07 04:46:27: New connection from 192.168.178.36:61317 on port 1883.
2024-04-07 04:46:27: New client connected from 192.168.178.36:61317 as esp_dev (p2, c1, k15, u'esp32').
2024-04-07 04:46:27: No will message specified.
2024-04-07 04:46:27: Sending CONNACK to esp_dev (0, 0)
2024-04-07 04:46:27: Received SUBSCRIBE from esp_dev
2024-04-07 04:46:27: esp/config/0C:B8:15:F4:1F:FC (QoS 1)
2024-04-07 04:46:27: esp_dev 1 esp/config/0C:B8:15:F4:1F:FC
2024-04-07 04:46:27: Sending SUBACK to esp_dev
2024-04-07 04:46:27: Sending PUBLISH to esp_dev (d0, q0, r1, m0, 'esp/config/0C:B8:15:F4:1F:FC', ... (108 bytes))
2024-04-07 04:46:27: Received PUBLISH from esp_dev (d0, q1, r0, m2, 'testTopic', ... (86 bytes))
2024-04-07 04:46:27: Sending PUBLISH to paho82806266301 (d0, q0, r0, m0, 'testTopic', ... (86 bytes))
2024-04-07 04:46:27: Sending PUBACK to esp_dev (m2, rc0)
2024-04-07 04:46:27: Received DISCONNECT from esp_dev
2024-04-07 04:46:27: Client esp_dev disconnected.

А это неудачный журнал Mosquitto, в котором он застревает в бесконечном цикле. Здесь вы можете видеть, что ESP АКТИВНО отключается от брокера после получения опубликованного сообщения. Это должен быть код в deserializePayload(), если isConfigUpToDate() возвращает false. Через 5–7 секунд он будет делать это снова и снова.
2024-04-07 05:31:34: New connection from 192.168.178.36:51254 on port 1883.
2024-04-07 05:31:34: New client connected from 192.168.178.36:51254 as esp_dev (p2, c1, k15, u'esp32').
2024-04-07 05:31:34: No will message specified.
2024-04-07 05:31:34: Sending CONNACK to esp_dev (0, 0)
2024-04-07 05:31:34: Received SUBSCRIBE from esp_dev
2024-04-07 05:31:34: esp/config/0C:B8:15:F4:1F:FC (QoS 1)
2024-04-07 05:31:34: esp_dev 1 esp/config/0C:B8:15:F4:1F:FC
2024-04-07 05:31:34: Sending SUBACK to esp_dev
2024-04-07 05:31:34: Sending PUBLISH to esp_dev (d0, q0, r1, m0, 'esp/config/0C:B8:15:F4:1F:FC', ... (108 bytes))
2024-04-07 05:31:34: Received DISCONNECT from esp_dev
2024-04-07 05:31:34: Client esp_dev disconnected.
2024-04-07 05:31:40: New connection from 192.168.178.36:60107 on port 1883.
2024-04-07 05:31:41: New client connected from 192.168.178.36:60107 as esp_dev (p2, c1, k15, u'esp32').
2024-04-07 05:31:41: No will message specified.
2024-04-07 05:31:41: Sending CONNACK to esp_dev (0, 0)
2024-04-07 05:31:41: Received SUBSCRIBE from esp_dev
2024-04-07 05:31:41: esp/config/0C:B8:15:F4:1F:FC (QoS 1)
2024-04-07 05:31:41: esp_dev 1 esp/config/0C:B8:15:F4:1F:FC
2024-04-07 05:31:41: Sending SUBACK to esp_dev
2024-04-07 05:31:41: Sending PUBLISH to esp_dev (d0, q0, r1, m0, 'esp/config/0C:B8:15:F4:1F:FC', ... (108 bytes))
2024-04-07 05:31:41: Received DISCONNECT from esp_dev
...
infinite loop here until the battery is drained from WiFi connecting
...

mosquitto.conf
...
autosave_interval 1800
autosave_on_changes true
persistence true
persistence_location /var/lib/mosquitto/
...


Подробнее здесь: https://stackoverflow.com/questions/782 ... cess-chain
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»