github Yeraze/meshmonitor v4.16.2

2 hours ago

MeshMonitor v4.16.2

The full release of the 4.16.2 line, after six release candidates. It adds a passive Coverage Report that replaces the Range Test module firmware 2.8 removed, likely-aircraft detection with age-out, flight trails and optional ADS-B flight matching, and asset tracking with full-history trails and timeline playback. Nodes, messages, route records and traffic charts now split by transport (RF, UDP, MQTT), and a per-source option corrects sign-flipped positions without changing stored data. Per-source Message Forwarding sits next to the Auto-Responder, and MeshCore gains client-side Ignore and Block, channel sorting and slot reordering, and remote logins that retry and can be cancelled. CARTO vector basemaps, a quick age filter and Group by Role on the Nodes tab, and adding a node from a contact URL round out the UI. Firmware OTA now runs on the selected source with its own TCP port and a board map that matches Meshtastic's release names. A security fix stops an MQTT broker source's Info and Device Config tabs from showing, or writing to, the primary TCP node. Many MeshCore, MQTT, mobile and iOS 27 fixes land as well.

Release post: https://meshmonitor.org/blog/2026-09-29-v4.16.2-release

Upgrade notes

  • MeshCore adverts default to zero-hop, and automated flood adverts are limited to one per hour per source. Saved configs with no mode set keep flooding but fall under the hourly limit.
  • MQTT and MeshCore sources no longer use the primary Meshtastic radio. Sends, device config and remote admin from those sources are refused with SOURCE_NOT_MESHTASTIC.
  • Longest Active and Record Holder cards need traceroute:read on the source, and Clear Record needs traceroute:write (previously info).
  • Fifteen migrations run on first boot (168–182). Migration 174 repairs PostgreSQL installs that were restored from a backup.

What's Changed

Features

  • feat(meshcore): client-side Ignore/Block for nodes and text patterns (#5408) (#5469)
  • feat: simple per-source message Forwarding next to Auto-Responder (#5446) (#5455)
  • feat(automations): add action.setAutomationEnabled (#5445) (#5454)
  • feat(map): CARTO vector basemaps + bundled CARTO Voyager Dark (#5448) (#5453)
  • feat: asset tracking Phase 3 — timeline playback (#5354) (#5422)
  • feat(mqtt): drop automation-originated packets at the bridge uplink (#5414) (#5418)
  • feat: asset tracking Phase 2 — full-history trail with shape-preserving thinning (#5354) (#5419)
  • feat: sign-flip follow-ups — geofences, traceroute snapshots, MeshCore (#5363) (#5412)
  • feat: asset tracking Phase 1 — asset flag, per-asset retention, forced trail (#5354) (#5411)
  • feat: detect and correct sign-flipped node positions (#5363) (#5409)
  • feat(map): separate clustering toggle from the Map Click Zoom Gate (#5407)
  • feat: ADS-B flight matching for likely aircraft (#5374) (#5410)
  • feat(meshcore): retry remote logins, wait longer, show progress, allow cancel (#5400) (#5405)
  • feat(meshcore): reorder channel slots on the companion (#5379) (#5397)
  • feat(unified-messages): show per-source hop count inline (#5366) (#5393)
  • feat(nodes): quick age filter on the Nodes tab (#5387) (#5394)
  • feat(meshcore): channel list sort dropdown and custom display order (#5385, #5379) (#5392)
  • feat: per-source First Heard for Meshtastic and MeshCore nodes (#5390) (#5395)
  • feat: likely-aircraft flight trails + MQTT position history, Phase 3 (#5364, #5365) (#5396)
  • feat: likely-aircraft age-out and reclassify as fixed, Phase 2 (#5364, #5365) (#5391)
  • feat: likely-aircraft detection, Phase 1 (#5364, #5365) (#5386)
  • feat(ui): name the three node-age controls by role and show the active window (#5344) (#5373)
  • feat(automation): {{ trigger.packetHash }} for MeshCore messages; verify channel frames by decryption (#5357) (#5359)
  • feat(coverage): saved surveys, Phase 4b (#5277) (#5353)
  • feat(coverage): gaps, summary, grid, export and deep links, Phase 4a (#5277) (#5348)
  • feat(meshcore): zero-hop adverts by default, hourly floor on automated floods (#5347)
  • Add Discord Webhook DM/PUBLIC to User Scripts Gallery (#5346)
  • feat(coverage): MeshCore receptions on the Coverage Report, Phase 3 (#5277) (#5337)
  • feat(telemetry): purge telemetry outliers with preview (#5333) (#5335)
  • feat(coverage): MQTT gateway receivers for the Coverage Report, Phase 2 (#5277) (#5336)
  • feat(coverage): Coverage Report — measured RF coverage map, Phase 1 (#5277) (#5334)
  • feat(telemetry): per-transport traffic series + device-counter labels, Phase 3 (#5101) (#5332)
  • feat(transport): per-transport route records and message split, Phase 2 (#5101) (#5330)
  • feat(info): per-transport breakdown, Phase 1 (#5101) (#5329)
  • feat(enrichment): run NodeInfo Enrichment Fix All on a schedule (#5287) (#5322)
  • feat(nodes): add a node from a Meshtastic contact URL (#5317) (#5318)
  • feat(meshcore): decode MULTIPART and CONTROL payloads (#5308)
  • Add MULTIPART and CONTROL payload types (#5285)

Bug Fixes

  • fix(aircraft): let an aged-out aircraft come back on MQTT sources (#5478)
  • fix(nodes): compact the Nodes list header (#5477)
  • Fix login username field autocapitalize and autofill hints (#5430)
  • fix(dashboard): pin the topbar so iOS 27 stops fogging it (#5286) (#5328)
  • fix(ui): /settings fits a phone; geofence fields commit on blur (#5471)
  • fix(frontend): only poll MeshCore neighbors for MeshCore sources (#5472)
  • fix(repo): untrack tiles symlink and make dev tileserver opt-in (#5470)
  • fix(ui): contain settings maps, bound Automation number inputs (#5467)
  • fix(ui): /settings nav offset, embed modal a11y, en-US locale 404, heap telemetry 401 (#5468)
  • fix(ui): automation page i18n and layout follow-ups to #5465 (#5466)
  • fix(ui): full trigger placeholder on desktop, wrap geofence hints on phones (#5465)
  • fix(ui): keep trigger fields inside their cards on phones (#5463)
  • fix(ui): stop Automation and Configuration pages scrolling sideways on phones (#5462)
  • fix(config): full-width Status Message input with attached counter (#5457)
  • fix(config): show one Range Test notice on 2.8 builds (#5458)
  • fix(meshcore): drop corrupt contact frames and scrub binary node names (#5460)
  • fix(automation): stop phantom "Save changes" bar on the Automation page (#5459)
  • fix(meshcore): take Last Heard from the companion clock, not the sender's (#5339) (#5451)
  • fix(packet-monitor): drop fw2.8 NodeDB replay bursts from the packet log (#5426) (#5450)
  • fix(config): show module-excluded notice under its own section header (#5447) (#5449)
  • fix(firmware): match OTA board map to Meshtastic release names (#5423 follow-up) (#5433)
  • fix(firmware): run the OTA lifecycle on the selected source (#5432)
  • fix(firmware): allow OTA for Station G3 (#5423) (#5429)
  • fix(firmware): OTA uses the source's custom TCP port (#5424) (#5428)
  • fix: auto-favorite sweep stacking, distribution channel permissions, SQLite telemetry-types scope (#5427)
  • fix(meshcore): page the neighbour table so lists past 10 show (#5413) (#5425)
  • fix(nodes): wrap the Nodes list header controls instead of overflowing (#5420) (#5421)
  • fix(helm): add service.extraPorts to expose Virtual Node ports in K8s (#5417)
  • fix(firmware): search extracted firmware zip recursively for platform-nested binaries (#5403)
  • fix: date positions by observation, not replay arrival; sweep re-checks aircraft verdicts (#5401) (#5406)
  • fix(mesh-issues): exempt each source's local node from C2 over-broadcasting (#5388) (#5389)
  • fix(sources): MQTT sources no longer send or write config through the primary radio (#5375) (#5383)
  • fix: maxNodeAgeHours 0 in TX jobs, node metrics and VN replay (#5376) (#5384)
  • fix: read each source's local node number from the key the manager writes (#5377) (#5382)
  • fix(meshcore-vn): show PKI export/import status on the MeshCore Info view (#5381)
  • fix(meshcore-vn): handle the 10 unhandled companion commands (#5350) (#5372)
  • fix(mqtt): MQTT broker sources no longer show another source's Device Info (#5367) (#5371)
  • fix(meshcore): notify for new nodes first heard without a name (#5340) (#5370)
  • fix(neighbor-info): treat maxNodeAgeHours 0 as show-all on the server (#5338) (#5378)
  • fix: honor unlimited node age in source view (#5338) (#5352)
  • fix(meshcore): fall back to receipt time when a node's clock is drifted (#5342)
  • fix(meshcore): don't stamp lastHeard to "now" on a contact sync with no advert time (#5343)
  • fix(settings): restore Sorting section to Global Settings page (#5369)
  • fix(scripts): match release runs to the tag's commit in watch-release.sh (#5362)
  • fix(map): position-history heading triangle no longer blocks the dot beneath (#5356) (#5358)
  • fix(restore): reset PostgreSQL sequences after restore; migration 174 repairs restored installs (#5355)
  • fix(meshcore): stable node list, clear not-on-radio errors, unambiguous prefix lookups (#5349) (#5351)
  • fix(channels): delete the channel row, and shift cards while dragging (#5324) (#5326)
  • fix(mobile): node list fills the phone (#5316); blur gap without Version/NN (#5286) (#5319)
  • fix(lora): follow use_preset for bandwidth, and name presets 9-16 (#5320) (#5321)
  • fix(nodes): pick the unified position by observation, not by lastHeard (#5314)
  • fix(meshcore): match the shell's bottom-bar query so landscape lays out (#5312)
  • fix(mobile): hide the node-list arrow under the map sheet, contain long timezones (#5291) (#5313)
  • fix(header): keep top-bar text below iOS 27's home-screen status-bar blur (#5286) (#5309)
  • fix(analysis): count hops only from traceroutes the local node took part in (#5289) (#5290)
  • fix(mqtt): let MQTT-only deployments see their own data (#5283)

Performance

  • perf: make large node sets usable (#5284)

Documentation

Tests

  • test: give every react-i18next mock a stable t (#5474)
  • test: fix EmbedSettings dialog and MeshCore neighbours-config flakes (#5473)
  • test(telemetry): give the MySQL outlier batch-delete test 60s (#5461)
  • test(meshcore): stabilise MeshCoreChannelsView reorder tests (#5431)

Translations

  • Translated using Weblate (Indonesian) (#5464)

Dependencies

  • chore(deps): bump maplibre-gl from 6.10.0 to 6.11.2 (#5438)
  • chore(deps): bump the codeql-action group with 4 updates (#5440)
  • chore(deps): bump @tanstack/react-query from 5.102.8 to 5.103.2 (#5439)
  • chore(deps): bump lucide-react from 1.47.0 to 1.48.0 (#5442)
  • chore(deps): bump aedes from 1.1.2 to 1.2.0 (#5443)
  • chore(deps): bump the production-dependencies group across 1 directory with 11 updates (#5436)
  • chore(deps-dev): bump puppeteer from 25.11.0 to 25.12.0 (#5441)
  • chore(deps-dev): bump supertest from 7.2.2 to 7.3.0 (#5437)
  • chore(deps-dev): bump jsdom from 30.0.1 to 30.1.1 (#5444)
  • chore(deps-dev): bump the development-dependencies group with 2 updates (#5435)
  • chore(deps): bump docker/build-push-action from 7.3.0 to 7.4.0 (#5307)
  • chore(deps): bump docker/setup-buildx-action from 4.3.0 to 4.4.1 (#5306)
  • chore(deps): bump maplibre-gl from 6.9.0 to 6.10.0 (#5299)
  • chore(deps): bump emoji-picker-react from 4.20.7 to 4.22.2 (#5297)
  • chore(deps): bump lucide-react from 1.45.0 to 1.47.0 (#5300)
  • chore(deps): bump dotenv from 17.4.2 to 18.0.0 (#5301)
  • chore(deps): bump mqtt from 5.15.2 to 5.16.0 (#5303)
  • chore(deps): bump docker/setup-qemu-action from 4.3.0 to 4.4.0 (#5305)
  • chore(deps-dev): bump the development-dependencies group across 1 directory with 3 updates (#5295)
  • chore(deps): bump the codeql-action group with 4 updates (#5304)
  • chore(deps): bump the production-dependencies group with 5 updates (#5296)
  • chore(deps-dev): bump puppeteer from 25.10.0 to 25.11.0 (#5298)
  • chore(deps-dev): bump @tanstack/react-query-devtools (#5302)
  • chore(deps-dev): bump the vitest group with 3 updates (#5294)

Release

  • chore(release): bump to 4.16.2, and write its changelog, docs and blog post (#5479)
  • chore(release): bump to 4.16.2-rc6, and write its changelog section (#5476)
  • chore(release): bump to 4.16.2-rc5, and write its changelog section (#5434)
  • chore(release): bump to 4.16.2-rc4, and write its changelog section (#5398)
  • chore(release): bump to 4.16.2-rc3, and write its changelog section (#5360)
  • chore(release): bump to 4.16.2-rc2, and write its changelog section (#5325)
  • chore(release): bump to 4.16.2-rc1, and write its changelog section (#5315)

Issues Resolved

  • #5101 [FEAT] Per-transport breakdown: Record Holder, Radio Statistics, Network Statistics (follow-up to #5097)
  • #5277 [FEAT] MM-native Range Test: portnum 66 on private channel, connected-source only, guardrailed
  • #5286 iOS 27 status-bar backdrop-blur bleeds into fixed AppHeader
  • #5287 Schedule NodeInfo Enrichment Fix All (cron/interval auto-run)
  • #5289 Map Analysis hop shading still renders remote nodes as 0-hop/local when newest traceroute has empty route array (follow-up to #4570)
  • #5291 [BUG] v4.16.1 iOS 27 mobile: node-list arrow overlaps Map controls; custom POSIX timezone overflows field
  • #5292 Unified view position drift: mergeNodeRecords picks newest-lastHeard with valid fix, may select coarser precision over finer
  • #5293 Manual position-request responses stored per-source only; not reconciled to other sources' node records
  • #5311 MeshCore source page keeps its desktop layout in landscape: nav row lands mid-page, content pane empty
  • #5316 [BUG] v4.16.2-rc1 iOS 27 PWA: per-source node list doesn't fill viewport width — right-edge strip lets map interactions through
  • #5317 [FEAT] Add nodes using their URLs
  • #5320 [BUG] Modem presets above SHORT_TURBO show "Unknown (N)" and report the wrong LoRa frequency
  • #5324 [BUG] Deleted channel leaves an Empty Channel Slot
  • #5333 Feature: purge telemetry outliers (auto-detected or value threshold)
  • #5338 [BUG] Max node age = 0 hides all non-favorite nodes in per-source Nodes tab (useSourceView missing #4947 guard)
  • #5339 [BUG] Meshcore - messed up sorting on "receive time" / last heard due to node timestamp
  • #5340 [BUG] Meshcore - Notification on new nodes seems not to work
  • #5341 [BUG] Meshcore - Identification of nodes in Nodes List
  • #5344 [FEAT] Unify or clarify the three overlapping node-age controls (sidebar 2h stat, Settings max age, Map Features slider)
  • #5345 User Script Submission
  • #5349 [BUG] MeshCore: resolveContactByPrefix collides on shared short pubkey prefix — repeater misclassification, instant login-fail, intermittent partial contact list
  • #5350 [BUG] MeshCore Virtual Node: RemoveContact + 9 other companion commands unhandled — mobile app shows generic error on delete/rename/reset/reboot
  • #5354 [FEAT] Asset tracking mode — per-node retention, uncapped trail, timeline playback (superset of manual mobile pin)
  • #5356 [BUG] Position History: heading triangle blocks hover/click on the circle beneath
  • #5357 [FEAT] Expose MeshCore on-wire packet hash on 'A message is received' automation trigger
  • #5363 Detect and correct sign-flipped node positions (wrong-hemisphere data-entry mistakes)
  • #5364 [FEAT] Auto-Favorite: exclude nodes above configurable altitude (aircraft filter)
  • #5365 [FEAT] Map: altitude-based airplane filter/marker with 24h stale-position age-out
  • #5366 [FEAT] Unified Messages: show per-source hop count inline (number emoji badges)
  • #5367 [BUG] MQTT_BROKER source shows a different source's Device Info (Node ID / Name / Firmware) — reproduces on v4.16.2-rc2 and v4.16.2-rc3
  • #5368 [SUPPORT] Telemetry Dashboard
  • #5374 [FEAT] Cross-reference likely-aircraft nodes with ADS-B / OpenSky flight data
  • #5375 MQTT/MeshCore sources still fall back to the primary TCP radio for sends, channel writes, tx-status, and unread-DM count
  • #5376 maxNodeAgeHours = 0 still means "no nodes" in auto-traceroute, remote-admin scanner, metrics, and VN replay
  • #5377 localNodeNum setting key mismatch: writer uses localNodeNum_, readers use getSettingForSource
  • #5379 [FEAT] MeshCore: reorder channels via drag-and-drop in Channels settings
  • #5380 MeshCore VN PKI Export/Import status rows never render (live in Meshtastic-only Info tab)
  • #5385 [FEAT] MeshCore: sort dropdown for Channels page display order
  • #5387 [FEAT] Nodes tab: on-the-fly age filter (1d/3d/7d/30d) without changing global setting
  • #5388 [BUG] Mesh Issues C2 'Broadcasting too often' fires on MM's own directly-connected local nodes
  • #5390 [FEAT] Add "First Heard" field for MeshCore and Meshtastic nodes
  • #5400 [FEAT] Meshcore repeater login
  • #5401 [BUG] Fixed node keeps stale 'likely aircraft' flag after altitude drops below threshold (no recompute path)
  • #5402 [SUPPORT] Firmware OTA fails to find binaries in platform subdirectory (Meshtastic 2.8.0)
  • #5404 [FR] Separate map clustering toggle from the Map Click Zoom Gate
  • #5408 [FEAT] MeshCore: client-side Ignore/Block for nodes and text patterns
  • #5413 [BUG] Meshcore Neighbours
  • #5414 Drop automation-originated packets at MQTT bridge uplink
  • #5416 [BUG] K8s with Helm dosent open a virtual node Port
  • #5420 [BUG] Nodes list header controls don't wrap on the Map page (overflow at narrow width)
  • #5423 Add STATION_G3 to firmwareHardwareMap for OTA updates
  • #5424 [BUG] OTA firmware update ignores custom TCP port (always uses 4403)
  • #5426 [BUG] Packet Monitor logs NodeDB-replay bursts as fresh LoRa receptions (want_config_id handshake)
  • #5445 [FEAT] Automation action to enable/disable another automation by ID
  • #5446 [FEAT] Simple 'Forwarding' feature alongside Auto-Responder (with per-rule enable/disable)
  • #5447 [BUG] ModuleAvailabilityGate warning banner visually attaches to previous section
  • #5448 [FEAT] Richer dark OSM tile preset (land-use color, road shields) — beyond CARTO dark_all / Esri Dark Gray

New Contributors

Thank you to our first-time contributors:

And thanks to @zvx-echo6, @zaepho and @temalo for their contributions, and to the Weblate translators.

Full Changelog: v4.16.1...v4.16.2

🚀 MeshMonitor v4.16.2

📦 Installation

Docker (recommended):

docker run -d \
  --name meshmonitor \
  -p 8080:3001 \
  -v meshmonitor-data:/data \
  ghcr.io/Yeraze/meshmonitor:4.16.2

🧪 Testing

✅ All tests passed
✅ TypeScript checks passed
✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

📋 Changes

See commit history for detailed changes.

Don't miss a new meshmonitor release

NewReleases is sending notifications on new releases.