meshcore-mqtt-live-map/docs.md
2025-12-24 04:32:48 +00:00

4.5 KiB
Raw Blame History

Mesh Map Live: Implementation Notes

This document captures the state of the project and the key changes made so far, so a new Codex session can pick up without losing context.

Overview

This project renders live MeshCore traffic on a Leaflet + OpenStreetMap map. A FastAPI backend subscribes to MQTT (WSS/TLS), decodes MeshCore packets using @michaelhart/meshcore-decoder, and broadcasts device updates and routes over WebSockets to the frontend.

Key Paths

  • backend/app.py: FastAPI server, MQTT client, decoder integration, persistence, routing, role/name logic.
  • backend/static/index.html: Leaflet UI, markers, legends, routes, styles.
  • docker-compose.yaml: runtime configuration (reads values from .env).
  • .env.example: copy to .env and fill in MQTT + site metadata.
  • data/state.json: persisted device/trail/roles/names/routes (created at runtime).

Site Metadata (Title, Embeds, Branding)

Set these in .env to control the page title and social embeds:

  • SITE_TITLE, SITE_DESCRIPTION
  • SITE_OG_IMAGE, SITE_URL, SITE_ICON
  • SITE_FEED_NOTE (small line under the header)

The server injects these into backend/static/index.html placeholders at runtime, so Discord/Twitter previews use the correct values.

Runtime Commands (Typical Workflow)

  • docker compose up -d --build (run after any file changes).
  • docker compose logs -f meshmap-live (watch MQTT + decode logs).
  • curl -s http://localhost:8080/snapshot (current device map).
  • curl -s http://localhost:8080/stats (counters, route types).
  • curl -s http://localhost:8080/debug/last (recent MQTT decode/debug entries).

MQTT + Decoder

  • MQTT is WebSockets + TLS (MQTT_TRANSPORT=websockets, MQTT_TLS=true, MQTT_WS_PATH=/ or /mqtt).
  • Decoder uses Node + @michaelhart/meshcore-decoder installed in the container.
  • app.py writes a small Node helper and calls it to decode MeshCore packets.

Device Names + Roles

  • Names come from advert payloads or status messages when available.
  • Roles are only accepted from explicit decoder fields:
    • deviceRole/deviceRoleName (MeshCore advert flags), or role fields in payload.
    • Name-based role heuristics were removed to avoid mislabels.
  • Roles are not assigned to the receiver of a packet. For decoded packets, the role applies to the advertised pubkey (decoded location.pubkey or decoded_pubkey).
  • Roles persist to data/state.json with device_role_sources. Only explicit/override roles are restored on load.
  • Optional overrides: data/device_roles.json can force roles per device_id.

Routes / Message Paths

Routes are drawn when:

  • A packet contains a path list (decoder pathHashes or path), or
  • Multiple observers see the same message hash (fanout), or
  • As a fallback, when one hash maps to a known device, a direct line is drawn to the receiver.

If routes arent visible:

  • The packet may only include a single hop (path: ["24"]).
  • Other repeaters might not be publishing to MQTT, so the message is only seen by one observer.

Frontend Map UI

  • Legend includes Trace/Message/Advert line styles and Repeater/Companion/Room/Unknown dot colors.
  • Unknown markers were made more visible (larger, higher contrast gray).
  • Zoom control moved to bottom-right.
  • Route lines are thicker/bolder for large screens.

Persistence

  • Devices, trails, names, roles, and routes are saved to data/state.json.
  • On restart, devices should stay visible if state.json exists.
  • If stale/mis-labeled roles appear, delete data/state.json or remove role entries.

Troubleshooting Notes

  • If map is empty but MQTT is connected, check /debug/last for decoded payloads and payloadType.
  • If markers appear in the wrong place, inspect decoder_meta and location fields.
  • If roles flip incorrectly, verify role_target_id in /debug/last.
  • If routes dont show, verify message hashes appear under multiple receivers in MQTT.

Recent Fixes / Changes Summary

  • Added full WSS support and TLS options.
  • Integrated meshcore-decoder for advert/location + role parsing.
  • Added /stats, /snapshot, /debug/last, /debug/status endpoints.
  • Added persistence and state reload logic; safer role restore rules.
  • Added route drawing for traces/paths/messages with TTL cleanup.
  • Added fallback route when only one hop is known.
  • UI: route legend, role legend, and improved marker styles.
  • Roles now apply to advertised pubkey, not receiver.
  • Docker restarts are required after file changes (always run docker compose up -d --build).