Two-fix bundle on top of v0.7.1. One small UX feature for hop-chain debugging, one quiet-but-important correctness fix that was inflating node counts on the cloud catalog and producing intermittent garbled-but-readable text on the local mesh. Both ride together because they touch the same RX path. Pure-Python, no recompile needed.
- Drop
STAT_CRC_BADpackets at the HAL boundary instead of forwarding them to the decoder.SX1302Wrapper.receive()was logging the diagnostic WARNING for CRC-failed packets but still appending them to the returned packet list, withcrc_ok=Falseset on theConcentratorPacket. No downstream code (concentrator_source,packet_router, decoders) ever read thecrc_okfield, so RF-corrupted bytes flowed intoMeshtasticDecoder.decode()where the source-ID was extracted directly from the corrupted header. Three observable downstream symptoms produced by this: (1) phantom node IDs registered in the local SQLite node table and propagated up to the cloud DynamoDB node catalog, where a single bit-flip in the source-ID field creates a new "node" sharing all-but-one bit with a real source ID; (2) false ENCRYPTED packet attribution when the channel-hash byte was corrupted and stopped matching the LongFast hash; (3) garbled-but-readable text when AES-CTR XORed corrupted ciphertext with the keystream, producing mostly-correct plaintext with a few mangled characters. Hardware-validated on RAK V2: 14 historical phantoms in the local DB matched the bit-flip fingerprint of legitimate neighbors (7d8b98a9,a0dd8936, etc.), and zero new phantoms have entered the database since the fix. Cloud-sideactive_nodes_24hcount is expected to drop sharply over the 24-48h after fleet rollout. Closes #34. - Relay-node visibility on the dashboard. Surfaces the Meshtastic header
relay_nodebyte (the lowest byte of the last relay node's ID) through the decoder →Packetmodel → SQLite schema (with idempotentALTER TABLEmigration for existing installs) → WebSocket payload → dashboard packet feed. Source cells in the packet feed now read!source ↝ !relaywhenever the packet was relayed, with full short-ID resolution when the relay byte matches a known node in the local registry. Clicking a relayed packet draws a line on the map between the source marker and the relay marker so you can trace the hop chain visually. Direct (non-relayed) packets render as before. Real-world utility: tracing a hop chain back to a rooftop node and confirming its ERP from the RSSI/SNR pattern. hop_limiton outbound TX now honorsTransmitConfiginstead of being hardcoded to 3. Two paths (send_text_messageand the NodeInfo broadcaster) were ignoring the configured hop limit and using a hardcoded3regardless of what was set inlocal.yaml. Behavior is unchanged for installs running the default (still 3); fixes the silent "I sethop_limitin my yaml and it didn't take" gap. The dashboard's per-packet HOPS column (hop_used / hop_limit) now reflects the actual configured ceiling.- Internal: new
tests/test_sx1302_wrapper.pycovers the CRC_BAD drop contract (syntheticSTAT_CRC_BADinput is dropped,crc_bad_countincrements, the WARNING fires, the decoder is not reached). Newtests/test_relay_node_header.pycoversrelay_nodeheader byte parsing andPacket.relay_nodepopulation.tests/test_database_migration.pyextended for thepackets.relay_nodeALTER TABLE path. 297 tests passing, ruff clean.
Polish bundle on top of the v0.7.0 source-publication release. Edge-only, no cloud changes. Touches radio tab UX, branding, and a handful of small upgrade-path papercuts. Pure-Python, no recompile needed.
- Radio tab redesign. Reworked the Radio tab with an SDR-console aesthetic: status lamps, readout cards, an analog-style duty-cycle gauge, a new NodeInfo Broadcast card, and a sticky restart banner that floats at the top while you scroll instead of getting buried at the bottom of the page. Channels table behavior is unchanged.
- NodeInfo broadcast is now configurable from the dashboard. New card on the Radio tab shows live telemetry (next broadcast countdown, last-sent timestamp, current interval, status lamp), exposes preset chips (
Off / 5m / 30m / 1h / 3h / 6h / 12h / 24h) plus a free-form 5-1440 minute input, and aSend Nowbutton that fires an immediate NodeInfo packet without waiting for the next scheduled tick.interval_minutes: 0pauses periodic broadcasts; non-broadcast TX (DMs, replies) is unaffected. New telemetry keys (last_sent_at,next_due_at,running) onGET /api/config/nodeinfo. NewPOST /api/config/nodeinfo/sendendpoint. - Interval changes hot-reload without a service restart. Saving a new NodeInfo interval immediately wakes the broadcast loop and re-anchors the next-due time, including during the initial 60-second startup delay window. Pausing (
interval=0) cleanly idles the loop; resuming fires the next broadcast right away if one was already overdue. Onlystartup_delay_secondschanges still require a restart, and the UI says so. - Pending-changes cue on Save buttons. When the displayed NodeInfo interval differs from the saved value, an amber notification dot pulses at the top-right of the Save button so unsaved work is hard to miss. Clears automatically on save or page refresh.
- Save NodeInfo card auto-refreshes after a broadcast fires. Previously the countdown got stuck on "broadcasting..." until you reloaded the page.
- Send Advert button on the MeshCore Companion card now actually works. Previously it POSTed to the text-message endpoint with empty body, got rejected by the empty-text validation, and surfaced "Advert failed" with nothing in the logs. Added a dedicated
POST /api/messages/advertendpoint that callsMeshCoreTxClient.send_advert()directly. Reported by iceice400. - Branding consistency pass. All user-facing prose and log lines now read "Meshpoint" and "Meshradar" (one word, capital M) instead of "Mesh Point" and "Mesh Radar". Most importantly, the default Meshtastic NodeInfo
long_namebroadcast over RF now readsMeshpoint, so the device shows up correctly onmeshmap.net, the Meshtastic phone app, and neighbor MQTT envelopes. Other surfaces touched: dashboard header, browser tab title, FastAPI auto-docs, CLI prose (meshpoint setup,meshpoint status,wizard_meshcore), installer prose, systemd unit descriptions, and module docstrings. Code identifiers (CLI command name, Python module names, YAML keys) are unchanged: branding rule applies to prose only. - Duty cycle default now auto-derives from your region. Previously hardcoded to
1.0(the EU 1% etiquette ceiling) regardless of where you were. Newresolve_max_duty_percent()readsradio.regionand applies a conservative regional default (US: 10%, EU 868: 1%, ANZ: 10%, IN: 1%, KR: 1%, SG 923: 10%) unlessrelay.max_duty_percentis explicitly set inlocal.yaml. Source surfaced in the Radio tab duty gauge asregion_defaultvsuser_override. Seedocs/RADIO-CONFIG-EXPLAINED.mdfor how to override. - Mobile responsive polish. All four dashboard tabs (Dashboard, Stats, Messages, Radio) render cleanly on phone-width viewports. Validated with the official Playwright MCP at iPhone 14 Pro and Galaxy S24 viewports.
- Header
Meshradarbrand link. The "Meshradar" portion of the dashboard header is now a link tomeshradar.io(opens in new tab). The "Meshpoint" portion stays plain text. Requested by Parker WEST. - Setup wizard preserves your existing coordinates. Example coordinates in the location prompt now show neutral NYC values (
40.7128, -74.0060) instead of a developer-specific location. Existingdevice.latitude/device.longitudeinlocal.yamlare still preserved as the prompt default, so re-runningmeshpoint setupdoes not overwrite them. install.shupgrade-aware banner. When run on a Meshpoint that already has an existing install (detected viaconfig/local.yamlpresence ormeshpoint.serviceenabled), the closing banner now reads "Meshpoint upgrade to vX.Y.Z complete: restart the service" instead of the spurious "Reboot to apply SPI/UART changes" message that was misleading users on every v0.7.0+ upgrade. Fresh installs still see the full first-run flow.- MQTT topic clarification in
default.yaml. Added inline comments explaining thatmqtt.topic_rootandmqtt.regionare concatenated to form the full Meshtastic spec topic (<topic_root>/<region>/2/e/<channel>/<gateway>), and thatmqtt.regionis independent ofradio.region. Avoids the double-region footgun (msh/US/FL/US/...) where users assumetopic_rootis the complete prefix. - FastAPI app version follows
__version__. The auto-generated/docsSwagger header was hardcoded to0.1.0since v0.1.x. Now reads fromsrc.version.__version__so it matches the running release. - Internal: new
tests/test_messages_advert_route.py(5 tests, FastAPI TestClient pattern),tests/test_nodeinfo_broadcaster.py::TestNodeInfoBroadcasterHotReload(10 tests covering hot-reload, pause, resume, startup-delay interruption),tests/test_duty_cycle_resolver.py(region resolution + override semantics). 254 tests passing, ruff clean.
Distribution architecture change: the eleven core SX1302/MeshCore modules are now shipped as Python source files in src/{hal,capture,decode,transmit}/ instead of pre-compiled .cpython-*.so binaries. Behavior is identical to v0.6.8; the change is purely about distribution format. Closes issue #32.
- Source published. All eleven modules (HAL wrapper, channel-plan builder, GPS reader, concentrator capture source, SX1262 SPI source, AES-CTR crypto service, Meshtastic and Meshcore decoders, portnum handlers, packet router, Meshtastic packet builder) ship as plain
.pyfiles under the existing AGPL-3.0 license. Auditability and portability to non-aarch64 hardware become trivial. - Upgrade path uses
install.sh.scripts/install.shnow removes any.cpython-*.soleft behind by previous installs before the venv is set up. Aftergit pull, runsudo /opt/meshpoint/scripts/install.shfollowed bysudo systemctl restart meshpoint. Agit pullalone is not sufficient on existing v0.6.x devices: Python's import machinery would prefer the stale binary over the new source. - Boot-time stale-
.sodetection. A startup WARN fires (and lists the offending files) if compiled binaries somehow re-appear insrc/. Surfaces inmeshpoint logsso you can fix the install before behavior freezes at v0.6.x. - RX diagnostic logging. Every CRC_BAD packet on the SX1302 concentrator now logs a WARNING with the IF chain, SF, BW, RSSI, SNR, size, and a running CRC_BAD counter. Useful for diagnosing rapid-fire packet loss caused by overlapping LoRa transmissions on the same demodulator. Per-packet RX traces are also available via the new
MESHPOINT_DEBUG_RX=1environment variable (off by default). - Internal: retired the Cython build pipeline that produced the per-release
.cpython-*.soartifacts since it's no longer needed.
Pure-Python follow-up to v0.6.7. No core module recompile required: just git pull + systemctl restart. Fixes two user-visible regressions surfaced after v0.6.7 shipped, plus the long-standing PRIVATE_HW labeling on community maps.
- Auto-derived Node ID is now persisted to
local.yamlon first boot. v0.6.7 added stable Meshtastic identity but only displayed the derived value on the dashboard if you happened to also save the Radio settings page; until then the API kept returningnode_id_hex: ""and the field rendered blank. Reported by Parker WEST. The Meshpoint now writes the derived value totransmit.node_idautomatically the first time it falls back to thedevice_idderivation, then treats it as a normal pinned config value on every subsequent restart. Hint text on the Radio tab tracks the source ("Pinned in local.yaml. Edit to override." vs "Random fallback (no device ID configured).") so you can tell at a glance where the value came from. End-to-end validated on RAK V2 with a fresh derive → persist → reload cycle. - Hardware model now reports as
PORTDUINO(37) instead ofPRIVATE_HW(255). Reported by holmebrian. Other Meshpoints, MQTT gateways, andmeshmap.netwere displaying every Meshpoint as the generic "private hardware" label even though Meshtastic has had aPORTDUINOenum value for Linux-based nodes since 2.4. NewHW_MODEL_PORTDUINOconstant alongside the existingHW_MODEL_PRIVATE_HW, threaded throughNodeInfoBroadcasteras the default. Verified on a witness Meshtastic phone after the broadcast cycle (60 s after restart, then every 30 min). Existing nodes will pick this up automatically on their next NodeInfo decode. - Local Stats tab "Network" section now actually renders. The Hardware Models donut on the local dashboard was hidden for everyone, even though the underlying SQLite query was returning data (143 of 458 nodes had a populated
hardware_modelcolumn on the test RAK). Two bugs: (1) the section was section-level hidden until roles had data, but the deferred edge decoder bug filters role 0 (=CLIENT, the most common role) out at decode time, so roles is effectively always empty on v0.6.x; (2) theHW_NAMESlookup table on the frontend had drifted from the upstream MeshtasticHardwareModelenum, so any model that DID render was getting the wrong label. Fixed both: each chart now hides itself independently, the section appears as long as either has data, andHW_NAMESis regenerated frommesh.proto(covers 0..129 plus 255). The Device Roles chart will start populating once the v0.7.0 core module bundle ships the deferred decoder fix. - Internal: new
node_id_sourceproperty onTxService("config" / "derived" / "random") for API + dashboard introspection. Newpersist_derived_node_idconstructor flag for test isolation. Eight new tests covering source-tracking and the auto-persist path (success, no-op when pinned, no-op when random, swallowed PermissionError). Two new tests onNodeInfoBroadcasterfor the PORTDUINO default + override.
Stable Meshtastic identity, NodeInfo broadcasts, and a clutch of small reliability fixes. Core module recompile required. Fixes Meshtastic DMs sent from a Meshpoint never arriving at recipients, even though the dashboard showed "Sent". Reported by Max_Plastix.
- Stable
source_node_idper Meshpoint. Previously the Meshtastic node ID was randomly chosen on every service restart unless the user manually settransmit.node_idinlocal.yamlor via the dashboard radio tab. Recipients ended up seeing a brand new "ghost" Meshpoint each restart and never built a stable contact, so direct messages had nowhere to thread to. Resolution priority is now (1)transmit.node_idin config, (2) deterministic SHA-256 derivation from the provisioneddevice.device_idUUID (stable across reboots), (3) cryptographically random fallback with a startup WARN if neither is set. Reserved IDs (0x00000000,0xFFFFFFFF) are explicitly skipped. Existing manually-set node IDs are preserved. - Periodic NodeInfo broadcasts. New
NodeInfoBroadcasteradvertises the Meshpoint's identity (long name, short name, node ID, hardware modelPRIVATE_HW) on the mesh 60 seconds after startup and every 30 minutes after that. This is what makes recipient nodes (T-Beam, Heltec, etc.) form a contact for your Meshpoint so they can route DMs back to it. Samesource_node_idis used for both NodeInfo and outbound DMs/text so recipients see one consistent identity. - Setup wizard surfaces the resolved identity. The
meshpoint setupDevice step now prints the device ID, derived node ID, long name, and short name with their origin (existing configvsauto-generated) so you can see exactly what will be advertised on the mesh before saving. - Setup wizard preflight check.
meshpoint setupnow verifies write permission toconfig/local.yamland the existence of theconfig/directory before asking any of the eight questions, so it bails immediately with an actionable message instead of failing 60 seconds in after you've filled in the whole form. Hit by holmebrian during initial setup. - Wizard config preservation (carried over from disk). Untouched sections of
local.yaml(e.g.meshcore_usb,mqtt) are now preserved when re-runningmeshpoint setup, instead of getting wiped out by the wizard overlay. New_deep_mergehelper handles nested merges. 13 unit tests cover the merge semantics. - Relay marked experimental, log noise tamed. Relay TX has never worked end-to-end (see ROADMAP.md). When
relay.enabled: trueyou now get a one-line WARN banner at startup making this explicit. The per-packetRelay TX: no payload availablewarning now fires only once per process and drops to DEBUG for every subsequent skip, so logs stay readable while the v0.7.0 relay completion is in flight. - Cross-protocol sender-name leak in DMs fixed. Meshtastic inbound DMs were showing arbitrary MeshCore contact names ("Guzii_RedV4" leaking into a Meshtastic conversation, etc.) because the unscoped fallback in
_save_and_notifygrabbed the first availablemc:%node row regardless of the inbound packet's protocol, then persisted that wrong name back to the Meshtastic node row so it stuck across reconnects. Each fallback is now scoped to its own protocol, and a parallel Meshtastic source-id lookup now runs for inbound MT direct messages (mirroring the existing broadcast path). Found mid-validation while testing the v0.6.7 NodeInfo fix. - Auto-cleanup of pre-v0.6.7 contamination. New idempotent startup migration in
DatabaseManagerrepairs Meshtastic node rows whoselong_namewas overwritten by a MeshCore contact name in earlier versions. Affected rows have theirlong_namereset to NULL on first restart of v0.6.7; the next NodeInfo broadcast from the real node repopulates the correct name automatically. Migration is a no-op on clean databases. (Previously-stored corrupted message rows in themessagestable are not auto-repaired since they're an immutable per-message snapshot; delete the affected conversation if the historical naming bothers you.) docs/COMMON-ERRORS.mdgains entries for "Meshtastic DM shows Sent but recipient never gets it" (now fixed in v0.6.7) and "Two Meshpoints with the same node ID breaking the mesh" (only happens if youddclone an SD card without re-runningscripts/provision.py).docs/RADIO-CONFIG-EXPLAINED.mddocuments the three identity sources (dashboard / wizard / yaml), their resolution priority, and the fact that identity changes require a service restart.- Internal: new tests for
_resolve_node_id(8 cases),NodeInfoBroadcaster(8 cases),build_nodeinforound-trip through the decoder (8 cases, private repo), wizard preflight (4 cases), and the relay no-payload dedup (4 cases). 32 new tests total, all green.
MeshCore reliability patch. Small follow-up to v0.6.5 cleaning up rough edges around the MeshCore USB companion. No edge concentrator changes, no cloud changes.
- Companion connects cleanly on
systemctl restart meshpoint. ESP32-S3 boards (Heltec V3/V4 etc.) need 6-10 seconds to be USB-ready after a reboot, but the underlying meshcore library was giving up after 5. Bumped the handshake window so cold connects work the first time instead of needing a manual USB unplug. - Background reconnect with DTR soft-reset. When the initial handshake does miss anyway, the source now schedules a background reconnect with exponential backoff and pulses DTR low to soft-reset the chip on the second attempt onwards. Recovers in 30-50 seconds without user intervention. On boards where DTR is wired to RESET (the common case for ESP32 dev boards) this is a real hardware reset; on others it's a harmless no-op.
- Health check tuning. The MeshCore health check (in place since March) was sometimes treating slow but healthy responses as a dead connection and triggering a full reconnect cycle. We caught it on the RAK during this round of testing: every 2-3 minutes the source would tear down and rebuild, costing 15-20 seconds of MeshCore RX downtime each time. Whether this was happening on other Meshpoints in production is unknown; it was never surfaced as a user-visible symptom. The health check now passes a proper command timeout, skips the active probe when inbound events have arrived recently (proof of life), and tolerates a single transient miss before declaring the connection dead.
- Dashboard radio tab now shows real values. The MeshCore Companion card was stuck on
Name: Unknown / Frequency: ? MHz / SF: SF? / TX Power: ? dBmfor everyone. Dashboard was reading from the wrong source. It now reads from the same place themeshpoint meshcore-radioCLI does, which has always shown correct values. - Smarter
meshpoint meshcore-radioCLI. Now prompts for a full Pi reboot after applying new radio settings instead of doing a service restart that races the still-recovering USB CDC stack. Reboot is the reliable path; restarting the service mid-USB-enumeration leaves MeshCore in a half-connected state where messages don't flow. - Heltec V4 ACM-shift fix. The companion would temporarily move from
/dev/ttyACM0to/dev/ttyACM1during the post-config reboot, get pinned into yourlocal.yaml, then become unreachable after the next Pi reboot when the kernel re-assigned it back to/dev/ttyACM0. The CLI now switches your config toauto_detect: truewhenever it sees the port shift, so the companion is found wherever it lands across reboots. docs/COMMON-ERRORS.mdgains entries for the MeshCore handshake-failed log message and spurious health-check reconnects.- Demoted
No MeshCore USB device foundfrom WARNING to INFO with friendlier wording (it's an expected state if the source is enabled but no companion is currently plugged in, not an error). - Internal: fixed deprecated
asyncio.get_event_loop()pattern intests/test_message_repository.pyso the suite remains compatible with newer test files usingIsolatedAsyncioTestCase.
- Network watchdog reliability fix: the watchdog no longer triggers an infinite reboot loop on networks where the gateway blocks ICMP. Gateway pings now fall back to
8.8.8.8before a check is counted as a failure, and auto-reboot is disabled by default (REBOOT_THRESHOLD = 0). Stage 1 recovery (interface restart at 3 consecutive failures) is unchanged. To re-enable automatic reboots, editscripts/network_watchdog.pyand setREBOOT_THRESHOLDback to6. Startup banner now logs the active thresholds so you can confirm the policy at a glance. Thanks to first-time contributor @dotchance for catching this and shipping the fix. (#27) - Support documentation expansion: new
docs/FAQ.md,docs/HARDWARE-MATRIX.md,docs/COMMON-ERRORS.md,docs/RADIO-CONFIG-EXPLAINED.md, anddocs/MQTT-AND-MESHRADAR.md. README "Support and documentation" section reorganized into Setup / When-something-goes-wrong / Project groups. - SX1302 minimum bandwidth documented:
docs/HARDWARE-MATRIX.mdanddocs/RADIO-CONFIG-EXPLAINED.mdnow explain that the SX1302 concentrator cannot tune below 125 kHz, which is why MeshCore (62.5 kHz) requires a USB companion radio for RX.
- Meshtastic broadcast sender names: received messages on public channels (LongFast, etc.) now show the sending node's long name, short name, or hex ID. Previously the UI showed the conversation key (
broadcast:meshtastic:0) in place of the sender because the backend never resolved the source node for Meshtastic broadcast text packets. The v0.6.2 sender-name fix only covered MeshCore; this finishes the job for Meshtastic. (#19) - Defensive frontend filter: chat UI no longer renders strings starting with
broadcast:as a sender label if they ever slip through.
- TX channel hash fix: messages sent from the dashboard were going out with hash 0x02 (invisible to the mesh) instead of the correct 0x08. The primary channel name defaulted to blank, producing the wrong hash. Now defaults to "LongFast" matching Meshtastic firmware. (#21)
- Primary channel editable: channel 0 can now be renamed and saved from the Radio settings page. Previously edits reverted on refresh. (#13)
- Channel display cleanup: Radio settings shows the actual channel name (e.g. "LongFast") instead of "Primary (LongFast)".
- MQTT channel name fix: MQTT topics now use the actual channel name (LongFast, MediumFast, ShortFast, etc.) instead of
chXXhashes. NewChannelResolvermaps all 8 standard Meshtastic presets and supports user-configured channel keys. (#20) - Chat sender names: received messages now show the sender's node name or hex ID. Previously there was no way to tell who sent what. (#19)
- Chat day dividers: messages from different days are separated by date labels (Today, Yesterday, or the date) in the chat window.
- Espressif USB udev rule: installer adds a udev rule so Heltec V3/V4 and T-Beam ESP32-S3 USB serial devices are accessible to the meshpoint service user without manual group changes. (#12)
- Local stats dashboard: new Stats tab on the local dashboard with 12 live Chart.js charts: protocol split, packet types, RSSI distribution, signal quality, direct vs relayed, active nodes, device roles, hardware models, relay decisions, rejection reasons, and traffic timeline. All generated locally, no cloud needed.
- Enriched heartbeat: edge accumulates per-packet stats in memory and sends a batched summary to Meshradar in each heartbeat instead of the cloud processing every individual packet. Same data, significantly fewer backend operations. Savings scale with fleet size.
- Local topology layer: map tab gains a "Topology Links" toggle showing lines between nodes with RSSI/SNR tooltips.
- Farthest direct tracking: tracks the farthest direct (0-hop) node heard, with distance and signal strength, visible on the stats page.
- Relay rejection tracking: relay engine now records why packets are rejected (duplicate, rate limited, type filtered, signal bounds), visible in local stats.
- Native mesh messaging: send and receive Meshtastic messages from the browser. Broadcast to LongFast, talk on custom channels, DM individual nodes. MeshCore messaging via USB companion. SX1302 transmits with correct sync word and encryption.
- Chat UI: conversations organized by channel and contact. Signal info on every received bubble. Duplicate badge for relayed messages. History persisted locally.
- Radio config from dashboard: region, modem preset, frequency override, TX power, duty cycle, custom channels with PSKs, and TX toggle. All configurable from the Radio tab without SSH.
- Node discovery: live node cards with name, ID, protocol, hardware model, signal, battery, last seen. Detail drawer with signal history. DM from node card.
- Dashboard overhaul: messaging tab, node cards grid, radio settings page, frequency and SF columns in packet feed.
- CLI operational report:
meshpoint reportcommand with full-screen terminal dashboard: RX stats, traffic breakdown, signal averages, system metrics, health status. - Setup wizard improvements: unique random Meshtastic node ID per device (no collisions), MeshCore companion as its own wizard step.
- MQTT hotfix: shipped missing MQTT runtime files (publisher, formatter, pipeline wiring) that were absent from v0.5.4. MQTT config and docs were present but the code was not, so
mqtt.enabled: truehad no effect. Update and restart to activate MQTT publishing.
- MQTT gateway: dual-protocol MQTT publishing for Meshtastic (protobuf ServiceEnvelope) and MeshCore (JSON). Publishes to community maps (meshmap.net, NHmesh.live) and Home Assistant. Two-gate privacy model: MQTT is off by default, and only public channel traffic is published unless you explicitly allowlist a private channel. Each Meshpoint gets a unique node-format gateway ID that integrates natively with the Meshtastic ecosystem, appearing on meshmap.net, Liam Cottle's map, and other community tools. Optional JSON mirror for HA/Node-RED, auto-discovery sensor configs, and configurable location precision.
- Packet type filter (cloud): filter the Meshradar cloud packet feed by type (traceroute, position, text, etc.) and protocol (Meshtastic/MeshCore). Dropdown filters in the packets tab header.
- Setup wizard MQTT step:
meshpoint setupnow includes an MQTT opt-in prompt with broker selection and HA integration toggle.
- Multi-key decryption: packets on private Meshtastic channels now decrypt when channel keys are configured in
local.yaml. Previously only the default key was tried. (#5) - Heartbeat optimization: reduced upstream heartbeat interval for lower cloud costs.
- Core module binary fix: v0.5.1 shipped updated source but stale compiled
.sofiles. This release includes the correctly compiled binaries.
- Non-LongFast preset fix:
ConcentratorChannelPlan.from_radio_config()no longer ignores spreading factor and bandwidth when using the region's default frequency. EU_868 MediumFast (SF9/BW250), ShortFast, and other presets now work correctly. Previously, any preset at the default frequency was silently overridden to LongFast (SF11/BW250). (#4)
- Multi-region frequency support: 6 Meshtastic regions (US, EU_868, ANZ, IN, KR, SG_923) with auto-tuning concentrator and setup wizard region selector.
- Preset tuning: service channel SF and BW are configurable via
local.yaml. Supports MediumFast, ShortFast, ShortTurbo: not just LongFast. - Frequency override: set
frequency_mhzinlocal.yamlto tune to a non-default slot within your region. - Full portnum decoding: position speed/heading/altitude, power metrics, routing errors, NEIGHBORINFO, TRACEROUTE payloads.
meshpoint meshcore-radioCLI: switch MeshCore companion frequency without re-running the full wizard. Presets (US/EU/ANZ) or custom entry.- Startup banner accuracy: boot log shows the actual radio config, not just the region default.
- Config stability: empty YAML sections no longer crash the service on startup.
- Real-time packet streaming: cloud dashboard receives packets instantly via WebSocket. Live animated lines trace packets from source nodes to your Meshpoint on the map.
- Cloud map overhaul: marker clustering, signal heatmap layer, topology lines from neighborinfo data, and a live Recent Packets ticker panel.
- SenseCap M1 support: auto-detects SenseCap M1 carrier board via I2C probe during setup. Flash an SD card and go.
- 14 Meshtastic portnums decoded: TEXT, POSITION, NODEINFO, TELEMETRY, ROUTING, ADMIN, WAYPOINT, DETECTION_SENSOR, PAXCOUNTER, STORE_FORWARD, RANGE_TEST, TRACEROUTE, NEIGHBORINFO, MAP_REPORT, plus encrypted packet tracking.
- Device role extraction: node table shows CLIENT, ROUTER, REPEATER, TRACKER, SENSOR, and other roles from NodeInfo packets.
- Smart relay engine: deduplication, token-bucket rate limiting, hop/type/signal filtering, independent SX1262 TX path.
- Live dashboard UX: color-coded packet feed, decoded payload contents, 24h active node counts, version-based update indicator, and enlarged map view.
- Cloud dashboard tabs: tabbed layout with fleet view, interactive map controls, device-scoped filters, unified packet cards with signal strength bars, and public activity stream for visitors.
- MeshCore USB capture: new capture source for USB-connected MeshCore companion nodes. Auto-detects the device, configures radio frequency via the setup wizard (US/EU/ANZ presets or custom), with auto-reconnect and health monitoring. Startup banner shows all active sources.
- Custom frequency tuning: configurable SX1302 channel plan via
local.yaml. Validated on live hardware with LongFast (SF11/BW250). Dual-protocol HAL patch for simultaneous Meshtastic and MeshCore sync words.