refactor(snmp): publish radio stats as one coherent record

Per-field writes from the mesh task could be read mid-update by the
SNMP worker. Producers now publish a complete record through a mailbox
and the worker copies it into OID storage once per loop.
This commit is contained in:
agessaman committed 2026-09-21 16:05:54 -07:00
1 parent 0fc5ffe4a4
commit 5ddb13fafd
2 files changed
+54 -18

No files matched your search

+35 -16
View File
@@ -69,6 +69,22 @@ void MeshSNMPAgent::begin(const char* community) {
void MeshSNMPAgent::loop() {
if (!_running) return;
const RadioSnapshot snapshot = _radio_snapshot.read();
_packets_recv = snapshot.packets_recv;
_packets_sent = snapshot.packets_sent;
_recv_errors = snapshot.recv_errors;
_noise_floor = snapshot.noise_floor;
_last_rssi = snapshot.last_rssi;
_last_snr = snapshot.last_snr;
_sent_flood = snapshot.sent_flood;
_sent_direct = snapshot.sent_direct;
_recv_flood = snapshot.recv_flood;
_recv_direct = snapshot.recv_direct;
_total_air_time_secs = snapshot.total_air_time_secs;
_uptime_secs = snapshot.uptime_secs;
memcpy(_node_name, snapshot.node_name, sizeof(_node_name));
memcpy(_firmware_version, snapshot.firmware_version, sizeof(_firmware_version));
// Update memory and selected-network stats locally on Core 0.
_free_heap = (int)ESP.getFreeHeap();
_max_alloc = (int)ESP.getMaxAllocHeap();
@@ -91,18 +107,19 @@ void MeshSNMPAgent::updateRadioStats(
uint32_t sent_flood, uint32_t sent_direct,
uint32_t recv_flood, uint32_t recv_direct,
uint32_t total_air_time_secs, uint32_t uptime_secs) {
_packets_recv = (int)packets_recv;
_packets_sent = (int)packets_sent;
_recv_errors = (int)recv_errors;
_noise_floor = (int)noise_floor;
_last_rssi = (int)last_rssi;
_last_snr = (int)last_snr;
_sent_flood = (int)sent_flood;
_sent_direct = (int)sent_direct;
_recv_flood = (int)recv_flood;
_recv_direct = (int)recv_direct;
_total_air_time_secs = (int)total_air_time_secs;
_uptime_secs = (int)uptime_secs;
_radio_pending.packets_recv = (int)packets_recv;
_radio_pending.packets_sent = (int)packets_sent;
_radio_pending.recv_errors = (int)recv_errors;
_radio_pending.noise_floor = (int)noise_floor;
_radio_pending.last_rssi = (int)last_rssi;
_radio_pending.last_snr = (int)last_snr;
_radio_pending.sent_flood = (int)sent_flood;
_radio_pending.sent_direct = (int)sent_direct;
_radio_pending.recv_flood = (int)recv_flood;
_radio_pending.recv_direct = (int)recv_direct;
_radio_pending.total_air_time_secs = (int)total_air_time_secs;
_radio_pending.uptime_secs = (int)uptime_secs;
_radio_snapshot.publish(_radio_pending);
}
void MeshSNMPAgent::updateMQTTStats(int connected_slots, int queue_depth, int skipped_publishes) {
@@ -112,13 +129,15 @@ void MeshSNMPAgent::updateMQTTStats(int connected_slots, int queue_depth, int sk
}
void MeshSNMPAgent::setNodeName(const char* name) {
strncpy(_node_name, name, sizeof(_node_name) - 1);
_node_name[sizeof(_node_name) - 1] = '\0';
strncpy(_radio_pending.node_name, name, sizeof(_radio_pending.node_name) - 1);
_radio_pending.node_name[sizeof(_radio_pending.node_name) - 1] = '\0';
_radio_snapshot.publish(_radio_pending);
}
void MeshSNMPAgent::setFirmwareVersion(const char* version) {
strncpy(_firmware_version, version, sizeof(_firmware_version) - 1);
_firmware_version[sizeof(_firmware_version) - 1] = '\0';
strncpy(_radio_pending.firmware_version, version, sizeof(_radio_pending.firmware_version) - 1);
_radio_pending.firmware_version[sizeof(_radio_pending.firmware_version) - 1] = '\0';
_radio_snapshot.publish(_radio_pending);
}
#endif // WITH_SNMP
+19 -2
View File
@@ -3,6 +3,7 @@
#ifdef WITH_SNMP
#include <WiFiUdp.h>
#include "ObserverMailbox.h"
#include <SNMP_Agent.h>
// Temporary private enterprise OID base — replace with registered PEN when available.
@@ -22,8 +23,7 @@ public:
void begin(const char* community);
void loop();
// Called from the mesh task (Core 1) to push fresh stats into SNMP-visible variables.
// Copies are atomic for 32-bit aligned ints on ESP32, so no mutex needed.
// Loop-task producers publish a coherent record; the SNMP worker owns OID storage.
void updateRadioStats(uint32_t packets_recv, uint32_t packets_sent, uint32_t recv_errors,
int16_t noise_floor, int16_t last_rssi, int16_t last_snr,
uint32_t sent_flood, uint32_t sent_direct,
@@ -38,6 +38,23 @@ public:
bool isRunning() const { return _running; }
private:
struct RadioSnapshot {
int packets_recv = 0;
int packets_sent = 0;
int recv_errors = 0;
int noise_floor = 0;
int last_rssi = 0;
int last_snr = 0;
int sent_flood = 0;
int sent_direct = 0;
int recv_flood = 0;
int recv_direct = 0;
int total_air_time_secs = 0;
int uptime_secs = 0;
char node_name[32]{};
char firmware_version[32]{};
} _radio_pending;
ObserverMailbox<RadioSnapshot> _radio_snapshot;
WiFiUDP _udp;
SNMPAgent _snmp;
bool _running;