you 9f7233bc2d fix: VCR timeline tooltip on touch devices
Add touchmove/touchend handlers to show the time tooltip during touch
scrubbing on the timeline, mirroring the existing mousemove behavior.

closes #19
closes #27
closes #54
closes #57
closes #58
closes #59
closes #60
closes #61
closes #62
closes #63
closes #64

Additional fixes in this commit:
- #27: Add drag resize handle on feed panel right edge, persist width to localStorage
- #54: Add aria-describedby to heat/ghost toggles with sr-only descriptions
- #57: Refactor legend to use semantic ul/li with descriptive text, h3 headings
- #58: Wrap scope buttons in role=radiogroup, add role=radio and aria-checked
- #59: Add role=alertdialog to VCR prompt, auto-focus first button on show
- #60: Add legend toggle button visible on mobile to show/hide legend overlay
- #61: Position feed detail card as full-width bottom sheet on mobile
- #62: Add pin button to nav bar to prevent auto-hide
- #63: Adjust VCR.playhead when buffer is spliced to prevent stale indices
- #64: Standardize fetch limits to 2000 for both vcrRewind and vcrReplayFromTs
2026-03-19 21:11:59 +00:00
2026-03-18 19:34:05 +00:00
2026-03-18 19:34:05 +00:00
2026-03-18 19:55:28 +00:00
2026-03-18 19:34:05 +00:00
2026-03-18 19:34:05 +00:00
2026-03-18 19:34:05 +00:00
2026-03-18 19:34:05 +00:00

MeshCore Analyzer

Self-hosted, open-source MeshCore packet analyzer — a community alternative to the closed-source analyzer.letsmesh.net.

Collects MeshCore packets via MQTT, decodes them, and presents a full web UI with live packet feed, node map, channel chat, packet tracing, and more.

Features

  • Live Packet Feed — real-time WebSocket updates, filterable by type/region/observer
  • Interactive Map — Leaflet map with node markers by role, clustering, last-heard filters
  • Channel Chat — decoded group messages with sender names, @mentions, timestamps
  • Node Directory — searchable node list with role tabs, detail panel, advert timeline
  • Packet Tracing — follow packets across observers with SNR/RSSI timeline
  • Observer Status — health monitoring, packet counts, uptime
  • Dark Mode — toggle with sun/moon icon, persisted in localStorage
  • Global Search — search packets, nodes, and channels (Ctrl+K)

Quick Start

Prerequisites

  • Node.js 18+ (tested with 22.x)
  • MQTT broker (Mosquitto recommended) — optional, can inject packets via API

Install

git clone https://github.com/youruser/meshcore-analyzer.git
cd meshcore-analyzer
npm install

Configure

Edit config.json:

{
  "port": 3000,
  "mqtt": {
    "broker": "mqtt://localhost:1883",
    "topic": "meshcore/+/+/packets"
  },
  "channelKeys": {
    "public": "8b3387e9c5cdea6ac9e5edbaa115cd72"
  },
  "defaultRegion": "SJC",
  "regions": {
    "SJC": "San Jose, US",
    "SFO": "San Francisco, US",
    "OAK": "Oakland, US"
  }
}
Field Description
port HTTP server port (default: 3000)
mqtt.broker MQTT broker URL. Set to "" to disable MQTT and use API-only mode
mqtt.topic MQTT topic pattern for packet ingestion
channelKeys Named channel decryption keys (hex). public is the default MeshCore public channel
defaultRegion Default IATA region code for the UI
regions Map of IATA codes to human-readable region names

Run

node server.js

Open http://localhost:3000 in your browser.

Environment Variables

Variable Description
PORT Override config.json port
DB_PATH Override SQLite database path (default: data/meshcore.db)

Generate Test Data

To populate the analyzer with synthetic packets for testing/demo:

# Generate and inject 200 packets via API
node tools/generate-packets.js --api --count 200

# Or output as JSON
node tools/generate-packets.js --json --count 50

Run Tests

# End-to-end test (starts server, injects packets, validates all APIs)
DB_PATH=/tmp/test-e2e.db PORT=13590 node tools/e2e-test.js

# Frontend smoke test (validates pages load and render correctly)
DB_PATH=/tmp/test-fe.db PORT=13591 node tools/frontend-test.js

MQTT Setup

MeshCore packets flow into the analyzer via MQTT:

  1. Flash an observer node with MESH_PACKET_LOGGING=1 build flag
  2. Connect via USB to a host running meshcoretomqtt
  3. Configure meshcoretomqtt with your IATA region code and MQTT broker address
  4. Packets appear on topic meshcore/{IATA}/{PUBKEY}/packets

Alternatively, POST raw hex packets to POST /api/packets for manual injection.

Architecture

Observer Node → USB → meshcoretomqtt → MQTT Broker → Analyzer Server → WebSocket → Browser
                                                    → SQLite DB
                                                    → REST API

Project Structure

meshcore-analyzer/
├── config.json          # MQTT, channel keys, regions
├── server.js            # Express + WebSocket + MQTT + REST API
├── decoder.js           # Custom MeshCore packet decoder
├── db.js                # SQLite schema + queries
├── data/
│   └── meshcore.db      # Packet database (auto-created)
├── public/
│   ├── index.html       # SPA shell
│   ├── style.css        # Theme (light/dark)
│   ├── app.js           # Router, WebSocket, utilities
│   ├── packets.js       # Packet feed + byte breakdown
│   ├── map.js           # Leaflet map
│   ├── channels.js      # Channel chat
│   ├── nodes.js         # Node directory
│   ├── traces.js        # Packet tracing
│   └── observers.js     # Observer status
└── tools/
    ├── generate-packets.js  # Synthetic packet generator
    ├── e2e-test.js          # End-to-end API tests
    └── frontend-test.js     # Frontend smoke tests

License

MIT

Description
No description provided
Readme GPL-3.0 132 MiB
Languages
JavaScript 50.4%
Go 41%
CSS 4.3%
Shell 2.8%
Python 0.9%
Other 0.5%