Add warning to MQTT section

This commit is contained in:
Jack Kingsman
2026-03-02 14:01:43 -08:00
parent f059756064
commit 9e68544fe9
5 changed files with 23 additions and 8 deletions

View File

@@ -360,7 +360,7 @@ Optional MQTT integration forwards mesh events to an external broker for home au
- `meshcore/raw/gm:<channel_key>` — raw packet attributed to a channel
- `meshcore/raw/unrouted` — raw packets that couldn't be attributed
**Architecture**: `broadcast_event()` in `websocket.py` calls `mqtt_broadcast()` — a single hook covering all message and raw_packet broadcasts. The `MqttPublisher` in `app/mqtt.py` manages a background connection loop with auto-reconnect and backoff. Publishes are fire-and-forget (silent drop if disconnected). Connection state changes trigger toasts via `broadcast_error`/`broadcast_success`. The health endpoint includes `mqtt_status`.
**Architecture**: `broadcast_event()` in `websocket.py` calls `mqtt_broadcast()` — a single hook covering all message and raw_packet broadcasts. The `MqttPublisher` in `app/mqtt.py` manages a background connection loop with auto-reconnect and backoff. Publishes are fire-and-forget (silent drop if disconnected). Connection state changes trigger toasts via `broadcast_error`/`broadcast_success`. The health endpoint includes `mqtt_status` (`disabled` when no broker host is set, or when both publish toggles are off).
**Security**: MQTT password stored in plaintext in SQLite, consistent with the project's trusted-network design.

View File

@@ -722,7 +722,7 @@ SOFTWARE.
</details>
### @uiw/react-codemirror (4.25.5) — MIT
### @uiw/react-codemirror (4.25.4) — MIT
*License file not found in package.*
@@ -1380,7 +1380,7 @@ SOFTWARE.
</details>
### tailwind-merge (3.5.0) — MIT
### tailwind-merge (3.4.0) — MIT
<details>
<summary>Full license text</summary>

View File

@@ -106,19 +106,20 @@ app/
### MQTT publishing
- Optional forwarding of mesh events to an external MQTT broker.
- All config in `app_settings` (not env vars): `mqtt_broker_host`, `mqtt_broker_port`, `mqtt_username`, `mqtt_password`, `mqtt_use_tls`, `mqtt_topic_prefix`, `mqtt_publish_messages`, `mqtt_publish_raw_packets`.
- Disabled when `mqtt_broker_host` is empty.
- All config in `app_settings` (not env vars): `mqtt_broker_host`, `mqtt_broker_port`, `mqtt_username`, `mqtt_password`, `mqtt_use_tls`, `mqtt_tls_insecure`, `mqtt_topic_prefix`, `mqtt_publish_messages`, `mqtt_publish_raw_packets`.
- Disabled when `mqtt_broker_host` is empty, or when both publish toggles are off (`mqtt_publish_messages=false` and `mqtt_publish_raw_packets=false`).
- `broadcast_event()` in `websocket.py` calls `mqtt_broadcast()` — single hook covers all message and raw_packet events.
- `MqttPublisher` (`app/mqtt.py`) runs a background connection loop with auto-reconnect and exponential backoff (5s → 30s).
- Publishes are fire-and-forget; individual publish failures logged but not surfaced to users.
- Connection state changes surface via `broadcast_error`/`broadcast_success` toasts.
- Health endpoint includes `mqtt_status` field (`connected`, `disconnected`, `disabled`).
- Health endpoint includes `mqtt_status` field (`connected`, `disconnected`, `disabled`), where `disabled` covers both "no broker host configured" and "nothing enabled to publish".
- Settings changes trigger `mqtt_publisher.restart()` — no server restart needed.
- Topics: `{prefix}/dm:{key}`, `{prefix}/gm:{key}`, `{prefix}/raw/dm:{key}`, `{prefix}/raw/gm:{key}`, `{prefix}/raw/unrouted`.
### Community MQTT
- Separate publisher (`app/community_mqtt.py`) for sharing raw packets with the MeshCore community aggregator.
- Implementation intent: keep functional parity with the reference implementation at `https://github.com/agessaman/meshcore-packet-capture` unless this repository explicitly documents a deliberate deviation.
- Independent from the private `MqttPublisher` — different broker, authentication, and topic structure.
- Connects to the community broker (default `mqtt-us-v1.letsmesh.net:443`) via WebSockets over TLS.
- Authentication: Ed25519 JWT tokens signed with the radio's expanded "orlp" private key. Tokens expire after 24 hours; proactive renewal at 23 hours.

View File

@@ -228,8 +228,10 @@ LocalStorage migration helpers for favorites; canonical favorites are server-sid
- `bots`
- `mqtt_broker_host`, `mqtt_broker_port`, `mqtt_username`, `mqtt_password`
- `mqtt_use_tls`, `mqtt_tls_insecure`, `mqtt_topic_prefix`, `mqtt_publish_messages`, `mqtt_publish_raw_packets`
- `community_mqtt_enabled`, `community_mqtt_iata`, `community_mqtt_broker_host`, `community_mqtt_broker_port`, `community_mqtt_email`
`HealthStatus` includes `mqtt_status` (`"connected"`, `"disconnected"`, `"disabled"`, or `null`).
`HealthStatus` also includes `community_mqtt_status` with the same status values.
`RawPacket.decrypted_info` includes `channel_key` and `contact_key` for MQTT topic routing.

View File

@@ -252,14 +252,26 @@ export function SettingsMqttSection({
/>
<div className="text-xs text-muted-foreground space-y-2">
<div>
<p className="font-medium">Decrypted messages <span className="font-mono font-normal opacity-75">{'{'}id, type, conversation_key, text, sender_timestamp, received_at, paths, outgoing, acked{'}'}</span></p>
<p className="font-medium">
Decrypted messages{' '}
<span className="font-mono font-normal opacity-75">
{'{'}id, type, conversation_key, text, sender_timestamp, received_at,
paths, outgoing, acked{'}'}
</span>
</p>
<div className="font-mono ml-2 space-y-0.5">
<div>{mqttTopicPrefix || 'meshcore'}/dm:&lt;contact_key&gt;</div>
<div>{mqttTopicPrefix || 'meshcore'}/gm:&lt;channel_key&gt;</div>
</div>
</div>
<div>
<p className="font-medium">Raw packets <span className="font-mono font-normal opacity-75">{'{'}id, observation_id, timestamp, data, payload_type, snr, rssi, decrypted, decrypted_info{'}'}</span></p>
<p className="font-medium">
Raw packets{' '}
<span className="font-mono font-normal opacity-75">
{'{'}id, observation_id, timestamp, data, payload_type, snr, rssi,
decrypted, decrypted_info{'}'}
</span>
</p>
<div className="font-mono ml-2 space-y-0.5">
<div>{mqttTopicPrefix || 'meshcore'}/raw/dm:&lt;contact_key&gt;</div>
<div>{mqttTopicPrefix || 'meshcore'}/raw/gm:&lt;channel_key&gt;</div>