feat(mqtt): add per-slot packet filters for MQTT slots

Introduce per-slot packet filters to allow users to specify which
packet types are uploaded for each MQTT slot. This feature enhances
the flexibility of the MQTT bridge by enabling users to configure
allowlists for packet types, improving the efficiency of data
transmissions. The implementation includes updates to the WebConfig
interface, internal handling of packet filters, and necessary
modifications to the MQTT preferences structure.
This commit is contained in:
agessaman committed 2026-07-27 18:34:04 -07:00
1 parent 3c5b25c2cf
commit e00b29b4b8
17 files changed
+510 -22

No files matched your search

+23
View File
@@ -25,6 +25,7 @@
#include "bridges/MQTTBridge.h"
#include "MQTTConnectionPolicy.h" // classifySlotActivation() — "will this slot connect here?"
#include "MQTTDefaults.h"
#include "MQTTPacketFilter.h"
#endif
// Local copy of the busted-libc-safe atoi (the original in CommonCLI.cpp is static).
@@ -529,6 +530,20 @@ bool CommonCLI::handleObserverSetCmd(uint32_t sender_timestamp, const char* conf
savePrefs();
_callbacks->restartBridgeSlot(slot);
sprintf(reply, "OK - slot %d JWT audience cleared (using username/password auth)", slot + 1);
} else if (strcmp(subcmd, "filter") == 0 ||
strncmp(subcmd, "filter ", 7) == 0) {
// Empty/bare input resets to the backwards-compatible all-types default.
const char* filter_value = subcmd[6] == '\0' ? "" : &subcmd[7];
uint16_t filter_mask = 0;
if (!MQTTPacketFilter::parse(filter_value, &filter_mask)) {
strcpy(reply, "Error: filter must be all, none, or CSV packet types 0-15");
} else {
_mqtt_prefs.mqtt_slot_packet_filter[slot] = filter_mask;
savePrefs();
char filter_text[MQTTPacketFilter::kFilterTextSize];
MQTTPacketFilter::format(filter_mask, filter_text, sizeof(filter_text));
snprintf(reply, 160, "OK - slot %d packet types: %s", slot + 1, filter_text);
}
} else {
sprintf(reply, "unknown config: %s", config);
}
@@ -869,6 +884,14 @@ bool CommonCLI::handleObserverGetCmd(uint32_t sender_timestamp, const char* conf
} else {
strcpy(reply, "> (not set - custom slots use username/password auth)");
}
} else if (strcmp(subcmd, "filter") == 0) {
char filter_text[MQTTPacketFilter::kFilterTextSize];
if (MQTTPacketFilter::format(_mqtt_prefs.mqtt_slot_packet_filter[slot],
filter_text, sizeof(filter_text))) {
snprintf(reply, 160, "> %s", filter_text);
} else {
strcpy(reply, "Error: invalid stored packet filter");
}
} else if (memcmp(subcmd, "diag", 4) == 0) {
MQTTBridge::formatSlotDiagReply(reply, 160, slot);
} else {