feat: add MQTT downlink proxy support (subscribe + forward to radio)#155
Open
richardpowellus wants to merge 3 commits into
Open
feat: add MQTT downlink proxy support (subscribe + forward to radio)#155richardpowellus wants to merge 3 commits into
richardpowellus wants to merge 3 commits into
Conversation
- MQTT downlink proxy: subscribe to channel topics and forward messages to radio - LoRa-to-MQTT relay: re-encrypt received LoRa packets and publish to MQTT (firmware in proxy mode only uplinks self-originated packets) - Skip default channels (LongFast, etc.) to avoid serial link saturation from high-traffic public broker topics (~320 msgs/sec) - Self-loop prevention: filter messages published by own gateway ID - Fix double-region topic bug: mqtt.root already includes region - AES-CTR encryption with proper Meshtastic nonce format - JSON topic subscription support when json_enabled is set
d94e046 to
4656674
Compare
Add two new boolean toggles under 'MQTT Proxy' options section: - Enable MQTT Downlink Forwarding (default: off) - Enable LoRa-to-MQTT Uplink Relay (default: off) Both features default to disabled, preserving existing behavior for all current users. The toggles are available in both the initial setup flow and the options reconfiguration UI. The option values are threaded through: __init__.py -> api.py -> interface.py This ensures the new downlink subscription and LoRa-to-MQTT relay features are strictly opt-in.
- Update README with MQTT Proxy section documenting downlink forwarding, uplink relay, and configuration options - Add 43 tests covering: - Config constants and option access patterns - PSK expansion (empty, single-byte indices, AES-128/256 passthrough) - AES-CTR encryption round-trip and nonce format - Default channel filtering (LongFast, LongSlow, etc.) - Topic construction (no double-region bug) - Self-loop prevention - Relay gating (same-node, PKI, disconnected, default channel, uplink disabled) - Downlink forwarding gating - Subscribe topic filtering - Constructor parameter gating for enable_mqtt_downlink/enable_mqtt_uplink_relay - Add conftest.py with importlib-based loading to avoid homeassistant runtime dependency
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The existing MQTT proxy implementation (added in #135) only supports uplink — publishing radio-received messages to an MQTT broker. After connecting to the broker,
_maintain_mqtt_connection()simply awaits_is_stopped.wait(), never subscribing to any topics or forwarding incoming messages back to the radio.This means devices relying on the MQTT proxy for internet connectivity (e.g. USB-connected devices without WiFi, like the Tracker T1000-E) can publish to the mesh via MQTT but cannot receive messages from other nodes through the MQTT mesh network.
Changes
_maintain_mqtt_connection()await self._is_stopped.wait()with a downlink subscription call followed by anasync for message in self._mqtt_client.messagesloop that forwards incoming messages to the radio.New:
_subscribe_to_downlink_topics()downlink_enabled, and subscribes to{root}/{region}/2/e/{channel_name}/#.config_pb2.Config.LoRaConfig.RegionCode.Name()for clean region string lookup (no hardcoded map).New:
_forward_mqtt_to_radio()MqttClientProxyMessage→ToRadioprotobuf and sends to the radio via the existing connection._handle_mqtt_client_proxy_message()Testing
Tested on a Tracker T1000-E (firmware 2.6.11, no WiFi) connected via USB to Home Assistant (HAOS 2026.2.3) with Meshtastic HA integration v0.6.1. The device is in a remote area (North Bend, WA) unable to reach the Seattle/Bellevue mesh via LoRa alone.
After applying this patch:
mqtt.meshtastic.orgmsh/US/2/e/LongFast/#, etc.)Related
Completes the MQTT proxy feature started in #135 by adding the missing downlink (subscribe + forward) path.