mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-07-28 15:19:20 +00:00
Refactored the handling of observer-related settings by moving them from NodePrefs to a new MQTTPrefs structure. This change centralizes MQTT, WiFi, timezone, SNMP, and alert configurations, improving code organization and maintainability. The new structure allows for better separation of concerns and prepares the codebase for future enhancements.
113 lines
4.0 KiB
C++
113 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include <Mesh.h>
|
|
#include "CommonCLI.h"
|
|
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
#include "bridges/MQTTBridge.h"
|
|
#endif
|
|
|
|
/**
|
|
* Returns the label of a banned alert channel if \a secret16 matches one of
|
|
* the channels in the BANNED_ALERT_CHANNELS table (e.g. "PUBLIC", "#test",
|
|
* "#bot"), or nullptr otherwise. Centralized here so both AlertReporter and
|
|
* the CommonCLI `set alert.psk` / `set alert.hashtag` handlers can share one
|
|
* source of truth — adding a new banned channel is a one-line table edit.
|
|
*/
|
|
const char* alertReporterBannedChannelMatch(const uint8_t* secret16);
|
|
|
|
/**
|
|
* Convenience: hex-decodes \a psk_hex (32 lowercase/uppercase hex chars) and
|
|
* forwards to alertReporterBannedChannelMatch. Returns nullptr if not banned
|
|
* (or if the input isn't a valid 32-char hex string — only 16-byte secrets
|
|
* are present in the banned table).
|
|
*/
|
|
const char* alertReporterBannedChannelMatchHex(const char* psk_hex);
|
|
|
|
/**
|
|
* \brief Send-only group-channel "fault alert" reporter for repeater/observer
|
|
* builds.
|
|
*
|
|
* Polls WiFi and per-MQTT-slot outage timers from MQTTBridge. When any timer
|
|
* exceeds its configured threshold, floods a single PAYLOAD_TYPE_GRP_TXT
|
|
* message on the configured alert channel ("WiFi down 47m — MyObserver"),
|
|
* then arms a "recovered" message for the next state transition.
|
|
*
|
|
* The alert channel must be explicitly configured to either a private hex
|
|
* PSK (`set alert.psk`) or a hashtag name (`set alert.hashtag`); the
|
|
* well-known PUBLIC group key (and a small list of other auto-responder
|
|
* channels — see BANNED_ALERT_CHANNELS in AlertReporter.cpp) are rejected on
|
|
* purpose so fault alerts never spam community channels.
|
|
*
|
|
* Edge-triggered + rate-limited via NodePrefs::alert_min_interval_min so a
|
|
* flapping link cannot spam the channel.
|
|
*
|
|
* Designed to compile and run on any repeater build:
|
|
* - The channel-send path uses only mesh::Mesh primitives that already
|
|
* exist in the Dispatcher hierarchy (createGroupDatagram + sendFlood).
|
|
* - WiFi/MQTT polling is #ifdef WITH_MQTT_BRIDGE-gated; without it, the
|
|
* reporter still supports manual `alert test` sends.
|
|
*/
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
class AlertReporter {
|
|
public:
|
|
AlertReporter();
|
|
|
|
/**
|
|
* Wire up the reporter. Must be called from MyMesh::begin() after prefs
|
|
* are loaded. \a callbacks is optional — when non-null the reporter uses
|
|
* it to resolve a TransportKey scope for outgoing alert floods (so the
|
|
* packet rides the repeater's default scope or an `alert.region` override).
|
|
*/
|
|
void begin(NodePrefs* prefs, MQTTPrefs* obs, mesh::Mesh* mesh, CommonCLICallbacks* callbacks = nullptr);
|
|
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
/** Bridge can be (re)created lazily; pass nullptr to detach. */
|
|
void setBridge(MQTTBridge* bridge);
|
|
#endif
|
|
|
|
/**
|
|
* Re-derive the cached GroupChannel from \a alert_psk_hex. Call from the
|
|
* CLI hot-reload hook after `set alert.psk` / `set alert.hashtag` / `set alert on|off`.
|
|
*/
|
|
void onConfigChanged();
|
|
|
|
/**
|
|
* Cooperative tick. Fast: returns immediately if disabled, throttled
|
|
* internally to ~5 s checks. Safe to call every loop().
|
|
*/
|
|
void onLoop(unsigned long now_ms);
|
|
|
|
/**
|
|
* Send an arbitrary text immediately (used by `alert test` CLI). Returns
|
|
* false when disabled, PSK invalid, or the underlying flood-send fails.
|
|
* Bypasses the rate limiter and edge logic.
|
|
*/
|
|
bool sendText(const char* text);
|
|
|
|
private:
|
|
bool resolveChannel(mesh::GroupChannel& out) const;
|
|
bool sendChannel(const char* text);
|
|
void formatAge(unsigned long age_ms, char* out, size_t out_size) const;
|
|
|
|
enum FaultState { OK, FIRING };
|
|
struct Fault {
|
|
FaultState state;
|
|
unsigned long fired_at_ms; // millis() when we last sent a "down" alert
|
|
unsigned long last_outage_started_ms; // remembered so the recovered msg can quote duration
|
|
};
|
|
|
|
NodePrefs* _prefs;
|
|
MQTTPrefs* _obs;
|
|
mesh::Mesh* _mesh;
|
|
CommonCLICallbacks* _callbacks;
|
|
#ifdef WITH_MQTT_BRIDGE
|
|
MQTTBridge* _bridge;
|
|
Fault _wifi;
|
|
Fault _mqtt[RUNTIME_MQTT_SLOTS];
|
|
#endif
|
|
unsigned long _next_check_ms;
|
|
};
|
|
#endif // WITH_MQTT_BRIDGE
|