diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index dfd407b6..b3c6af7a 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -1601,27 +1601,7 @@ void MyMesh::buildStatsJson(char* buf, size_t buf_size) { (unsigned long)getNumRecvFlood(), (unsigned long)getNumRecvDirect(), (int)_mgr->getOutboundCount(0xFFFFFFFF), wifi_rssi, network_medium, ip, bridge ? bridge->getQueueSize() : 0); - if (pos < 0 || pos >= (int)buf_size - 3) return; // truncated; snprintf terminated it - bool first = true; - for (int i = 0; i < RUNTIME_MQTT_SLOTS; i++) { - MQTTBridge::SlotStatusSnapshot s; - if (!MQTTBridge::getSlotStatusSnapshot(i, &s)) continue; - // "filt" is omitted for the all-types default, so the portal only has to - // render the exception and the JSON stays inside the stats buffer. - char filt[24]; - filt[0] = '\0'; - if (s.filter_mask != MQTTPacketFilter::kAllPacketTypes) { - snprintf(filt, sizeof(filt), ",\"filt\":%u", (unsigned)s.filter_mask); - } - int n = snprintf(buf + pos, buf_size - pos, - "%s{\"n\":%d,\"name\":\"%s\",\"state\":\"%s\",\"ok\":%lu,\"err\":%lu%s}", - first ? "" : ",", i + 1, s.name, s.state, s.publish_ok, s.publish_err, - filt); - if (n < 0 || n >= (int)(buf_size - pos)) break; - pos += n; - first = false; - } - snprintf(buf + pos, buf_size - pos, "]}"); + MQTTBridge::appendSlotStatsJson(buf, buf_size, pos); } #endif @@ -1748,10 +1728,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 runs in a separate FreeRTOS task on Core 0, so we don't call bridge.loop() here + // MQTT I/O runs in its worker; bridge.loop() publishes loop-owned inputs only. mesh::Mesh::loop(); #ifdef WITH_MQTT_BRIDGE + if (bridge) bridge->loop(); // A timed-out stop keeps the bridge down until the MQTT task acknowledges it. // Release the withheld resources whenever that late ack lands, and restart // only a bridge that is still meant to be running. diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 1eba3892..9512a245 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -1403,27 +1403,7 @@ void MyMesh::buildStatsJson(char* buf, size_t buf_size) { (unsigned long)getNumRecvFlood(), (unsigned long)getNumRecvDirect(), (int)_mgr->getOutboundCount(0xFFFFFFFF), wifi_rssi, network_medium, ip, bridge ? bridge->getQueueSize() : 0); - if (pos < 0 || pos >= (int)buf_size - 3) return; // truncated; snprintf terminated it - bool first = true; - for (int i = 0; i < RUNTIME_MQTT_SLOTS; i++) { - MQTTBridge::SlotStatusSnapshot s; - if (!MQTTBridge::getSlotStatusSnapshot(i, &s)) continue; - // "filt" is omitted for the all-types default, so the portal only has to - // render the exception and the JSON stays inside the stats buffer. - char filt[24]; - filt[0] = '\0'; - if (s.filter_mask != MQTTPacketFilter::kAllPacketTypes) { - snprintf(filt, sizeof(filt), ",\"filt\":%u", (unsigned)s.filter_mask); - } - int n = snprintf(buf + pos, buf_size - pos, - "%s{\"n\":%d,\"name\":\"%s\",\"state\":\"%s\",\"ok\":%lu,\"err\":%lu%s}", - first ? "" : ",", i + 1, s.name, s.state, s.publish_ok, s.publish_err, - filt); - if (n < 0 || n >= (int)(buf_size - pos)) break; - pos += n; - first = false; - } - snprintf(buf + pos, buf_size - pos, "]}"); + MQTTBridge::appendSlotStatsJson(buf, buf_size, pos); } #endif @@ -1568,6 +1548,7 @@ void MyMesh::loop() { mesh::Mesh::loop(); #ifdef WITH_MQTT_BRIDGE + if (bridge) bridge->loop(); // A timed-out stop keeps the bridge down until the MQTT task acknowledges it. // Release the withheld resources whenever that late ack lands, and restart // only a bridge that is still meant to be running. diff --git a/src/helpers/AlertReporter.cpp b/src/helpers/AlertReporter.cpp index 4a58ad61..bc198553 100644 --- a/src/helpers/AlertReporter.cpp +++ b/src/helpers/AlertReporter.cpp @@ -247,11 +247,12 @@ void AlertReporter::onLoop(unsigned long now_ms) { for (int i = 0; i < n; i++) { AlertFaultPolicy::Fault& f = _mqtt[i]; - if (!_bridge->isSlotEnabledAndAttempted(i)) { + const MQTTBridge::SlotOutageSnapshot slot = _bridge->getSlotOutageSnapshot(i); + if (!slot.monitored) { AlertFaultPolicy::rearmIfDisabled(f); continue; } - const uint32_t outage_start = (uint32_t)_bridge->getSlotCurrentOutageStartMs(i); + const uint32_t outage_start = slot.started_ms; const AlertFaultPolicy::OutageSnapshot snap = AlertFaultPolicy::fromStartMs(outage_start); AlertFaultPolicy::TickResult r = AlertFaultPolicy::tick( @@ -259,7 +260,7 @@ void AlertReporter::onLoop(unsigned long now_ms) { if (r.action == AlertFaultPolicy::Action::FireDown) { char text[100]; AlertFaultPolicy::formatMqttDown(text, sizeof(text), i + 1, - _bridge->getSlotPresetName(i), + slot.name, r.duration_ms); if (sendChannel(text)) { AlertFaultPolicy::commitDown(f, now, outage_start); @@ -267,7 +268,7 @@ void AlertReporter::onLoop(unsigned long now_ms) { } else if (r.action == AlertFaultPolicy::Action::FireRecovered) { char text[100]; AlertFaultPolicy::formatMqttRecovered(text, sizeof(text), i + 1, - _bridge->getSlotPresetName(i), + slot.name, r.duration_ms); sendChannel(text); AlertFaultPolicy::commitRecovered(f);