# MeshCore Analyzer [![Go Server Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/.badges/go-server-coverage.json)](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml) [![Go Ingestor Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/.badges/go-ingestor-coverage.json)](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml) [![Frontend Tests](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/.badges/frontend-tests.json)](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml) [![Frontend Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/.badges/frontend-coverage.json)](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml) [![Deploy](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml/badge.svg)](https://github.com/Kpa-clawbot/meshcore-analyzer/actions/workflows/deploy.yml) > High-performance mesh network analyzer powered by Go. Sub-millisecond packet queries, ~300 MB memory for 56K+ packets, real-time WebSocket broadcast, full channel decryption. Self-hosted, open-source MeshCore packet analyzer β€” a community alternative to the closed-source `analyzer.letsmesh.net`. Collects MeshCore packets via MQTT, decodes them in real time, and presents a full web UI with live packet feed, interactive maps, channel chat, packet tracing, and per-node analytics. ## ⚑ Performance The Go backend serves all 40+ API endpoints from an in-memory packet store with 5 indexes (hash, txID, obsID, observer, node). SQLite is for persistence only β€” reads never touch disk. | Metric | Value | |--------|-------| | Packet queries | **< 1 ms** (in-memory) | | All API endpoints | **< 100 ms** | | Memory (56K packets) | **~300 MB** (vs 1.3 GB on Node.js) | | WebSocket broadcast | **Real-time** to all connected browsers | | Channel decryption | **AES-128-ECB** with rainbow table | See [PERFORMANCE.md](PERFORMANCE.md) for full benchmarks. ## ✨ Features ### πŸ“‘ Live Trace Map Real-time animated map with packet route visualization, VCR-style playback controls, and a retro LCD clock. Replay the last 24 hours of mesh activity, scrub through the timeline, or watch packets flow live at up to 4Γ— speed. ![Live VCR playback β€” watch packets flow across the Bay Area mesh](docs/screenshots/MeshVCR.gif) ### πŸ“¦ Packet Feed Filterable real-time packet stream with byte-level breakdown, Excel-like resizable columns, and a detail pane. Toggle "My Nodes" to focus on your mesh. ![Packets view](docs/screenshots/packets1.png) ### πŸ—ΊοΈ Network Overview At-a-glance mesh stats β€” node counts, packet volume, observer coverage. ![Network overview](docs/screenshots/mesh-overview.png) ### πŸ“Š Node Analytics Per-node deep dive with interactive charts: activity timeline, packet type breakdown, SNR distribution, hop count analysis, peer network graph, and hourly heatmap. ![Node analytics](docs/screenshots/node-analytics.png) ### πŸ’¬ Channel Chat Decoded group messages with sender names, @mentions, timestamps β€” like reading a Discord channel for your mesh. ![Channels](docs/screenshots/channels1.png) ### πŸ“± Mobile Ready Full experience on your phone β€” proper touch controls, iOS safe area support, and a compact VCR bar. Live view on iOS ### And More - **11 Analytics Tabs** β€” RF, topology, channels, hash stats, distance, route patterns, and more - **Node Directory** β€” searchable list with role tabs, detail panel, QR codes, advert timeline - **Packet Tracing** β€” follow individual packets across observers with SNR/RSSI timeline - **Observer Status** β€” health monitoring, packet counts, uptime, per-observer analytics - **Hash Collision Matrix** β€” detect address collisions across the mesh - **Channel Key Auto-Derivation** β€” hashtag channels (`#channel`) keys derived via SHA256 - **Multi-Broker MQTT** β€” connect to multiple brokers with per-source IATA filtering - **Dark / Light Mode** β€” auto-detects system preference, map tiles swap too - **Theme Customizer** β€” design your theme in-browser, export as `theme.json` - **Global Search** β€” search packets, nodes, and channels (Ctrl+K) - **Shareable URLs** β€” deep links to packets, channels, and observer detail pages - **Protobuf API Contract** β€” typed API definitions in `proto/` - **Accessible** β€” ARIA patterns, keyboard navigation, screen reader support ## Quick Start ### Docker (Recommended) No Go installation needed β€” everything builds inside the container. ```bash git clone https://github.com/Kpa-clawbot/meshcore-analyzer.git cd meshcore-analyzer ./manage.sh setup ``` The setup wizard walks you through config, domain, HTTPS, build, and run. ```bash ./manage.sh status # Health check + packet/node counts ./manage.sh logs # Follow logs ./manage.sh backup # Backup database ./manage.sh update # Pull latest + rebuild + restart ./manage.sh mqtt-test # Check if observer data is flowing ./manage.sh help # All commands ``` See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for the full deployment guide β€” HTTPS options (auto cert, bring your own, Cloudflare Tunnel), MQTT security, backups, and troubleshooting. ### Configure Copy `config.example.json` to `config.json` and edit: ```json { "port": 3000, "mqtt": { "broker": "mqtt://localhost:1883", "topic": "meshcore/+/+/packets" }, "mqttSources": [ { "name": "remote-feed", "broker": "mqtts://remote-broker:8883", "topics": ["meshcore/+/+/packets"], "username": "user", "password": "pass", "iataFilter": ["SJC", "SFO", "OAK"] } ], "channelKeys": { "public": "8b3387e9c5cdea6ac9e5edbaa115cd72" }, "defaultRegion": "SJC" } ``` | Field | Description | |-------|-------------| | `port` | HTTP server port (default: 3000) | | `mqtt.broker` | Local MQTT broker URL (`""` to disable) | | `mqttSources` | External MQTT broker connections (optional) | | `channelKeys` | Channel decryption keys (hex). Hashtag channels auto-derived via SHA256 | | `defaultRegion` | Default IATA region code for the UI | | `dbPath` | SQLite database path (default: `data/meshcore.db`) | ### Environment Variables | Variable | Description | |----------|-------------| | `PORT` | Override config port | | `DB_PATH` | Override SQLite database path | ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Docker Container β”‚ β”‚ β”‚ Observer β†’ USB β†’ β”‚ Mosquitto ──→ Go Ingestor ──→ SQLite DB β”‚ meshcoretomqtt β†’ MQTT ──→│ β”‚ β”‚ β”‚ Go HTTP Server ──→ WebSocket β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Caddy (HTTPS) β†β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ Browser ``` **Two-process model:** The Go ingestor handles MQTT ingestion and packet decoding. The Go HTTP server loads all packets into an in-memory store on startup (5 indexes for fast lookups) and serves the REST API + WebSocket broadcast. Both are managed by supervisord inside a single container with Caddy for HTTPS and Mosquitto for local MQTT. ## MQTT Setup 1. **Flash an observer node** with `MESH_PACKET_LOGGING=1` build flag 2. **Connect via USB** to a host running [meshcoretomqtt](https://github.com/Cisien/meshcoretomqtt) 3. **Configure meshcoretomqtt** with your IATA region code and MQTT broker address 4. **Packets appear** on topic `meshcore/{IATA}/{PUBKEY}/packets` Or POST raw hex packets to `POST /api/packets` for manual injection. ## Project Structure ``` meshcore-analyzer/ β”œβ”€β”€ cmd/ β”‚ β”œβ”€β”€ server/ # Go HTTP server + WebSocket + REST API β”‚ β”‚ β”œβ”€β”€ main.go # Entry point β”‚ β”‚ β”œβ”€β”€ routes.go # 40+ API endpoint handlers β”‚ β”‚ β”œβ”€β”€ store.go # In-memory packet store (5 indexes) β”‚ β”‚ β”œβ”€β”€ db.go # SQLite persistence layer β”‚ β”‚ β”œβ”€β”€ decoder.go # MeshCore packet decoder β”‚ β”‚ β”œβ”€β”€ websocket.go # WebSocket broadcast β”‚ β”‚ └── *_test.go # 327 test functions β”‚ └── ingestor/ # Go MQTT ingestor β”‚ β”œβ”€β”€ main.go # MQTT subscription + packet processing β”‚ β”œβ”€β”€ decoder.go # Packet decoder (shared logic) β”‚ β”œβ”€β”€ db.go # SQLite write path β”‚ └── *_test.go # 53 test functions β”œβ”€β”€ proto/ # Protobuf API definitions β”œβ”€β”€ public/ # Vanilla JS frontend (no build step) β”‚ β”œβ”€β”€ index.html # SPA shell β”‚ β”œβ”€β”€ app.js # Router, WebSocket, utilities β”‚ β”œβ”€β”€ packets.js # Packet feed + hex breakdown β”‚ β”œβ”€β”€ map.js # Leaflet map + route visualization β”‚ β”œβ”€β”€ live.js # Live trace + VCR playback β”‚ β”œβ”€β”€ channels.js # Channel chat β”‚ β”œβ”€β”€ nodes.js # Node directory + detail views β”‚ β”œβ”€β”€ analytics.js # 11-tab analytics dashboard β”‚ └── style.css # CSS variable theming (light/dark) β”œβ”€β”€ docker/ β”‚ β”œβ”€β”€ supervisord-go.conf # Process manager (server + ingestor) β”‚ β”œβ”€β”€ mosquitto.conf # MQTT broker config β”‚ β”œβ”€β”€ Caddyfile # Reverse proxy + HTTPS β”‚ └── entrypoint-go.sh # Container entrypoint β”œβ”€β”€ Dockerfile # Multi-stage Go build + Alpine runtime β”œβ”€β”€ config.example.json # Example configuration β”œβ”€β”€ test-*.js # Node.js test suite (frontend + legacy) └── tools/ # Generators, E2E tests, utilities ``` ## For Developers ### Test Suite **380 Go tests** covering the backend, plus **150+ Node.js tests** for the frontend and legacy logic, plus **49 Playwright E2E tests** for browser validation. ```bash # Go backend tests cd cmd/server && go test ./... -v cd cmd/ingestor && go test ./... -v # Node.js frontend + integration tests npm test # Playwright E2E (requires running server on localhost:3000) node test-e2e-playwright.js ``` ### Generate Test Data ```bash node tools/generate-packets.js --api --count 200 ``` ### Migrating from Node.js If you're running an existing Node.js deployment, see [docs/go-migration.md](docs/go-migration.md) for a step-by-step guide. The Go engine reads the same SQLite database and `config.json` β€” no data migration needed. ## Contributing Contributions welcome. Please read [AGENTS.md](AGENTS.md) for coding conventions, testing requirements, and engineering principles before submitting a PR. **Live instance:** [analyzer.00id.net](https://analyzer.00id.net) β€” all API endpoints are public, no auth required. ## License MIT