Refactor MQTTBridge to utilize FreeRTOS for improved task management and responsiveness

- Moved MQTT processing to a dedicated FreeRTOS task on Core 0, enhancing non-blocking behavior.
- Implemented a FreeRTOS queue for thread-safe packet handling, replacing the previous circular buffer approach.
- Updated WiFi initialization and connection management to occur within the FreeRTOS task, improving overall system responsiveness.
- Enhanced logging and error handling for MQTT connections and packet processing.
- Cached broker and analyzer server statuses to reduce redundant checks and improve efficiency.
This commit is contained in:
agessaman
2026-01-21 20:28:36 -08:00
parent 56f98997e6
commit ed27ebd015
5 changed files with 703 additions and 145 deletions
+2 -2
View File
@@ -1174,11 +1174,11 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
void MyMesh::loop() {
// Check radio FIRST to ensure we don't miss incoming packets
// MQTT processing can take time, so we prioritize radio reception
// MQTT processing runs in a separate FreeRTOS task on Core 0, so we don't call bridge.loop() here
mesh::Mesh::loop();
#ifdef WITH_BRIDGE
bridge.loop();
// bridge.loop() is now handled by FreeRTOS task on Core 0 - no need to call it here
#endif
if (next_flood_advert && millisHasNowPassed(next_flood_advert)) {
+1 -1
View File
@@ -898,7 +898,7 @@ void MyMesh::loop() {
// MQTT processing can take time, so we prioritize radio reception
mesh::Mesh::loop();
#ifdef WITH_MQTT_BRIDGE
bridge.loop();
// bridge.loop() is now handled by FreeRTOS task on Core 0 - no need to call it here
#endif
if (millisHasNowPassed(next_push) && acl.getNumClients() > 0) {
File diff suppressed because it is too large Load Diff
+28 -1
View File
@@ -9,6 +9,13 @@
#include <Timezone.h>
#include "helpers/JWTHelper.h"
#ifdef ESP_PLATFORM
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>
#endif
#if defined(MQTT_DEBUG) && defined(ARDUINO)
#include <Arduino.h>
// USB CDC-aware debug macros: only print if Serial is ready (non-blocking check)
@@ -96,10 +103,19 @@ private:
};
static const int MAX_QUEUE_SIZE = 10;
// FreeRTOS queue for thread-safe packet queuing
#ifdef ESP_PLATFORM
QueueHandle_t _packet_queue_handle;
TaskHandle_t _mqtt_task_handle;
SemaphoreHandle_t _raw_data_mutex; // Mutex for raw radio data
#else
// Fallback to circular buffer for non-ESP32 platforms
QueuedPacket _packet_queue[MAX_QUEUE_SIZE];
int _queue_head;
int _queue_tail;
int _queue_count;
#endif
int _queue_count; // Protected by queue operations or mutex
// NTP time sync
WiFiUDP _ntp_udp;
@@ -151,6 +167,10 @@ private:
// Configuration validation state
bool _config_valid;
// Cached broker connection status (updated in callbacks to avoid redundant checks)
bool _cached_has_brokers;
bool _cached_has_analyzer_servers;
// Throttle logging for disconnected broker messages
unsigned long _last_no_broker_log;
static const unsigned long NO_BROKER_LOG_INTERVAL = 30000; // Log every 30 seconds max
@@ -172,6 +192,13 @@ private:
void connectToBrokers();
void processPacketQueue();
bool publishStatus(); // Returns true if status was successfully published
// FreeRTOS task function (runs on Core 0)
#ifdef ESP_PLATFORM
static void mqttTask(void* parameter);
void mqttTaskLoop(); // Main loop for MQTT task
void initializeWiFiInTask(); // WiFi initialization moved to task
#endif
void publishPacket(mesh::Packet* packet, bool is_tx,
const uint8_t* raw_data = nullptr, int raw_len = 0,
float snr = 0.0f, float rssi = 0.0f);
+21 -1
View File
@@ -103,7 +103,27 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
if (len > sz) { len = sz; }
int err = _radio->readData(bytes, len);
if (err != RADIOLIB_ERR_NONE) {
MESH_DEBUG_PRINTLN("RadioLibWrapper: error: readData(%d)", err);
// Throttle error logging to avoid spam (CRC errors are common in noisy environments)
static unsigned long last_crc_error_log = 0;
static unsigned long crc_error_count = 0;
unsigned long now = millis();
crc_error_count++;
// Log every 10 seconds max, or on first error
if (last_crc_error_log == 0 || (now - last_crc_error_log > 10000)) {
MESH_DEBUG_PRINTLN("RadioLibWrapper: error: readData(%d) - %lu errors in last 10s", err, crc_error_count);
last_crc_error_log = now;
crc_error_count = 0;
}
// For CRC mismatch errors (-7), reset radio state to prevent stuck conditions
// Similar to CustomLR1110's handling of header errors
if (err == -7) { // RADIOLIB_ERR_CRC_MISMATCH
// Call standby() to reset radio to known-good state
// This helps recover from false packet detections or corrupted state
_radio->standby();
}
len = 0;
} else {
// Serial.print(" readData() -> "); Serial.println(len);