# pyMC Console [![GitHub Release](https://img.shields.io/github/v/release/dmduran12/pymc_console-dist)](https://github.com/dmduran12/pymc_console-dist/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) A modern web dashboard for monitoring and managing your [MeshCore](https://meshcore.co.uk/) LoRa mesh repeater. Built on [pyMC_Repeater](https://github.com/rightup/pyMC_Repeater) by [RightUp](https://github.com/rightup), pyMC Console provides real-time visibility into your mesh network with an intuitive, feature-rich interface. ## How It All Fits Together The MeshCore Python ecosystem has three components: ``` ┌─────────────────────────────────────────────────────────────┐ │ pyMC Console │ │ (this repo - web dashboard UI) │ │ │ │ • React dashboard served on port 8000 │ │ • Visualizes packets, topology, stats │ │ • manage.sh installer handles everything │ └─────────────────────┬───────────────────────────────────────┘ │ uses API from ┌─────────────────────▼───────────────────────────────────────┐ │ pyMC_Repeater │ │ (RightUp's repeater daemon) │ │ │ │ • Python daemon that runs the repeater │ │ • Provides REST API on port 8000 │ │ • Handles packet forwarding, logging, config │ └─────────────────────┬───────────────────────────────────────┘ │ built on ┌─────────────────────▼───────────────────────────────────────┐ │ pyMC_core │ │ (RightUp's protocol library) │ │ │ │ • Low-level MeshCore protocol implementation │ │ • Radio drivers (SX1262, SX1276) │ │ • Packet encoding/decoding │ └─────────────────────────────────────────────────────────────┘ ``` **Key points:** - **Console does NOT replace Repeater** — they work together - Console's `manage.sh` installs both Repeater and Console side-by-side - Console provides the web UI; Repeater provides the backend API and radio control - You can upgrade Console independently without touching Repeater/Core ## Features ### Dashboard - **Live packet metrics** — Received, forwarded, dropped packets with sparkline charts - **TX Delay Recommendations** — Slot-based delay optimization with network role classification (edge/relay/hub/backbone) - **LBT Insights widgets** — Channel health, collision risk, noise floor, link quality at a glance - **Time range selector** — View stats from 20 minutes to 7 days - **Recent packets** — Live feed of incoming traffic with centralized polling (every 3s) ![Dashboard](docs/images/dashboard.png) ### Statistics - **Airtime utilization** — RX/TX utilization spectrum with peak and mean metrics - **Link quality polar** — Neighbor signal strength plotted by compass bearing - **Network composition** — Breakdown of repeaters, companions, and room servers - **Packet types treemap** — Distribution of ADVERT, TXT_MSG, ACK, RESPONSE, etc. - **RF noise floor** — Noise floor heatmap showing interference patterns over time - **Prefix disambiguation** — Health metrics for the topology inference system ![Statistics](docs/images/statistics.png) ### Contacts & Topology - **Interactive map** — MapLibre GL with dark theme, neighbor positions, and smooth animations - **3D terrain mode** — Toggle real-world topographic terrain with hillshading; all markers and edges drape onto the landscape - **3D arc edges** — Topology edges and neighbor lines render as elevated arcs via deck.gl PathLayer (GPU-accelerated) - **Viterbi HMM path decoding** — Hidden Markov Model resolves prefix collisions using physics-based transition costs and observation evidence - **Ghost node discovery** — Unknown repeaters detected when no known candidate is geographically plausible; locations estimated from anchor midpoints - **Deep Analysis** — One-click full topology rebuild from 75K packets with Viterbi decoding - **Edge confidence** — Line thickness and opacity scale with observation count and certainty - **Animated edges** — Trace-in effect on toggle, smooth fade-out - **Filter toggles** — Solo view for hub nodes, direct neighbors, or traffic-based filtering - **Loop detection** — Identifies redundant paths (double-line rendering) - **High-contrast markers** — Light fill with dark outline ensures visibility against any overlay - **Path health panel** — Health scores, weakest links, and latency estimates for observed routes - **Mobile node detection** — Identifies volatile nodes that appear/disappear frequently - **Wardriving coverage overlay** — H3 hexagonal tiles from external coverage servers (e.g., coverage.wcmesh.com) with SNR-based coloring ![Topology Map](docs/images/topology.png) ### Packets - **Searchable history** — Filter by type, route, time range - **Packet details** — Hash, path, payload, signal info, duplicates - **Path visualization** — Interactive map showing packet route with hop confidence ### Settings - **Mode toggle** — Forward (repeating) or Monitor (RX only) - **Duty cycle** — Enable/disable enforcement - **Radio config** — Live frequency, power, SF, bandwidth changes - **Theme selection** — Six color schemes (Seoul256, Gruvbox, Deus, Gotham, Sonokai, Kanagawa) - **Background images** — Multiple ambient backgrounds with adjustable brightness ![Settings](docs/images/settings.png) ### System & Logs - **System resources** — 20-minute rolling CPU and memory utilization chart - **Disk usage** — Storage utilization with progress bar - **Temperature** — Multi-sensor temperature gauges with threshold coloring - **Live logs** — Stream from repeater daemon with DEBUG/INFO toggle ![System](docs/images/system.png) ## Quick Start ### Requirements - Raspberry Pi (3, 4, 5, or Zero 2 W) - LoRa module (SX1262 or SX1276 based) - Raspbian/Raspberry Pi OS (Bookworm recommended) ### Installation ```bash # Clone this repository git clone https://github.com/dmduran12/pymc_console-dist.git pymc_console cd pymc_console # Run the installer (requires sudo) sudo bash manage.sh install ``` > **⚠️ Important: Branch Selection** > > During installation, you'll be asked to select a pyMC_Repeater branch. **Select `feat/dmg`** (the default/recommended option). This branch contains the login/authentication functionality required for the dashboard to work properly. > > If you select `dev` or `main`, you may encounter "error 200" or login issues. The installer will: 1. Install all system dependencies (Python, pip, etc.) 2. Clone and install [pyMC_Repeater](https://github.com/rightup/pyMC_Repeater) as a sibling directory 3. Install [pyMC_core](https://github.com/rightup/pyMC_core) (the protocol library) 4. Deploy the Console web dashboard 5. Configure and start the systemd service **After installation, your directory structure looks like:** ``` ~/pymc_console/ ← Console (this repo) ~/pyMC_Repeater/ ← Repeater daemon (cloned by installer) /opt/pymc_repeater/ ← Installed repeater files /opt/pymc_console/ ← Installed console files ``` Once complete, access your dashboard at `http://:8000` ## Management Menu After installation, run `sudo bash manage.sh` to access the management menu: ``` ┌─────────────────────────────────────┐ │ pyMC Console Management │ ├─────────────────────────────────────┤ │ 1. Start Service │ │ 2. Stop Service │ │ 3. Restart Service │ │ 4. View Logs │ │ 5. Configure Radio │ │ 6. Configure GPIO │ │ 7. Upgrade │ │ 8. Uninstall │ │ 9. Exit │ └─────────────────────────────────────┘ ``` ### Menu Options - **Start/Stop/Restart** — Control the repeater service - **View Logs** — Live log output from the repeater - **Configure Radio** — Set frequency, power, bandwidth, SF via preset selection - **Configure GPIO** — Set up SPI bus and GPIO pins for your LoRa module - **Upgrade** — Pull latest updates and reinstall - **Uninstall** — Remove the installation completely ## Upgrading To update to the latest version, use the TUI menu: ```bash cd pymc_console sudo bash manage.sh ``` Select **Upgrade** and choose: - **Console UI only** — Updates just the web dashboard (recommended, quick) - **Full upgrade** — Updates Console + pulls latest pyMC_Repeater/pyMC_core **Note:** You can safely upgrade Console without affecting your Repeater installation. This is useful when you want new dashboard features but your repeater is running stable. ## Configuration ### Radio Settings Use the **Configure Radio** menu option, or edit directly: ```bash sudo nano /etc/pymc_repeater/config.yaml ``` Key settings: ```yaml radio: frequency: 927875000 # Frequency in Hz spreading_factor: 7 # SF7-SF12 bandwidth: 62500 # Bandwidth in Hz tx_power: 28 # TX power in dBm coding_rate: 6 # 4/5, 4/6, 4/7, or 4/8 ``` ### Advanced: DIO2 and DIO3 Configuration Some LoRa modules require specific DIO pin configurations. These are **independent settings** that serve different purposes: - **DIO3 (TCXO)** — Temperature Compensated Crystal Oscillator control. Set `use_dio3_tcxo: true` if your module has a TCXO that needs DIO3 for voltage supply. - **DIO2 (RF Switch)** — Antenna RF switch control for TX/RX path switching. Set `use_dio2_rf: true` if your module requires DIO2 to control an external RF switch. > **Note:** These settings are available on the pyMC_Repeater `dev` branch (which uses pyMC_core `dev`). The `main` branch hardcodes `setDio2RfSwitch(False)`. Example for modules requiring both: ```yaml radio: use_dio3_tcxo: true # Enable TCXO via DIO3 use_dio2_rf: true # Enable RF switch via DIO2 (dev branch only) ``` **Important:** Setting `use_dio3_tcxo: true` does NOT automatically enable DIO2. They are independent configurations for different hardware features. ### Service Management ```bash # Check status sudo systemctl status pymc-repeater # Start/stop/restart sudo systemctl start pymc-repeater sudo systemctl stop pymc-repeater sudo systemctl restart pymc-repeater # View live logs sudo journalctl -u pymc-repeater -f ``` ## Hardware Requirements - **Raspberry Pi** (3, 4, 5, or Zero 2 W recommended) - **LoRa Module** — SX1262 or SX1276 based (e.g., Waveshare SX1262, LILYGO T3S3) - **SPI Connection** — Module connected via SPI with GPIO for reset/busy/DIO1 ### Tested Modules - Waveshare SX1262 HAT - LILYGO T3S3 (via USB serial) - Ebyte E22 modules - Heltec LoRa 32 ## Troubleshooting ### "Error 200" or Login Issues This typically means you installed with the wrong pyMC_Repeater branch. The login functionality is only available in the `feat/dmg` branch. **To fix:** ```bash cd pymc_console sudo bash manage.sh upgrade ``` Select **Full pyMC Stack** upgrade and choose the `feat/dmg` branch. > **Note:** When entering the branch name, use `feat/dmg` (not just `dmg`). ### Service won't start ```bash # Check for errors sudo journalctl -u pymc-repeater -n 50 # Verify config syntax cat /etc/pymc_repeater/config.yaml ``` ### No packets being received 1. Verify SPI is enabled: `ls /dev/spidev*` 2. Check GPIO configuration in manage.sh → Configure GPIO 3. Confirm frequency matches your network ### Dashboard not loading 1. Verify service is running: `sudo systemctl status pymc-repeater` 2. Check if port 8000 is accessible: `curl http://localhost:8000/api/stats` ### "Radio presets file not found" warning This warning during installation is non-fatal. The installer will continue and you can configure radio settings manually. The presets are fetched from an API; if the API is unavailable, common presets are offered as fallback options. ## Uninstalling ```bash cd pymc_console sudo bash manage.sh ``` Select **Uninstall** from the menu. This removes: - `/opt/pymc_repeater` (installation) - `/etc/pymc_repeater` (configuration) - `/var/log/pymc_repeater` (logs) - The systemd service ## How It Works ### Mesh Topology Analysis The dashboard reconstructs network topology from packet paths. MeshCore packets contain 2-character hex prefixes representing the route through the mesh: ``` Packet path: ["FA", "79", "24", "19"] Origin → Hop1 → Hop2 → Local ``` **The Challenge**: Multiple nodes may share the same 2-char prefix (1 in 256 collision chance). The system uses a **Viterbi HMM decoder** to find the most likely sequence of actual nodes: #### Viterbi Path Decoding Inspired by [d40cht/meshcore-connectivity-analysis](https://github.com/d40cht/meshcore-connectivity-analysis), the decoder treats path disambiguation as a Hidden Markov Model problem: - **States** — All candidate nodes matching each prefix, plus a "ghost" state for unknown nodes - **Priors** — Based on recency (recently-seen nodes are more likely) and disambiguation confidence - **Transitions** — Physics-based costs using geographic distance and LoRa range constraints **Key principle: Observation beats theory.** When edge observations have ≥80% confidence, real-world evidence overrides physics-based costs. #### Ghost Node Discovery When no known candidate is geographically plausible for a prefix, the decoder selects a "ghost" state. These are aggregated to discover unknown repeaters: - **Clustering** — Ghost observations grouped by prefix - **Location estimation** — Weighted centroid of anchor node midpoints - **Confidence scoring** — Based on observation count, common neighbors, and location variance - **UI panel** — Shows likely-real ghost nodes with estimated coordinates and adjacent known nodes #### Four-Factor Scoring (Pre-Viterbi) Before Viterbi decoding, candidates are scored using four-factor analysis inspired by [meshcore-bot](https://github.com/agessaman/meshcore-bot): 1. **Position (15%)** — Where in paths does this prefix typically appear? 2. **Co-occurrence (15%)** — Which prefixes appear adjacent to this one? 3. **Geographic (35%)** — How close is the candidate to anchor points? 4. **Recency (35%)** — How recently was this node seen? **Key techniques:** - **Recency scoring** — Exponential decay `e^(-hours/12)` favors recently-active nodes - **Age filtering** — Nodes not seen in 14 days are excluded from consideration - **Dual-hop anchoring** — Candidates scored by distance to both previous and next hops (a relay must be within RF range of both neighbors) - **Score-weighted redistribution** — Appearance counts redistributed proportionally by combined score The system maintains up to 75,000 packets in session memory (~2.5 days at 30k/day) for comprehensive topology evidence. ![Prefix Disambiguation](docs/images/disambiguation.png) ### Edge Rendering Topology edges are rendered with visual cues indicating confidence: - **Line thickness** — Scales from 1.5px (5 validations) to 10px (100+ validations) - **Validation threshold** — Edges require 5+ certain observations to render - **Certainty conditions** — An edge is "certain" when: - Both endpoints have ≥0.6 confidence (HIGH threshold), OR - The destination has ≥0.9 confidence (VERY_HIGH threshold), OR - It's the last hop to local node - **Inclusion threshold** — Edges require ≥0.4 confidence (MEDIUM threshold) for topology - **Trace animation** — Edges "draw" from point A to B when topology is enabled - **Fade animation** — Edges smoothly fade out when topology is disabled - **Loop edges** — Redundant paths rendered as parallel double-lines in accent color ### 3D Terrain & Visualization The Contacts map supports full 3D terrain rendering: - **Terrain tiles** — AWS Terrarium elevation data (free, no API key) - **Hillshading** — Visual depth tuned for dark map themes - **3D arcs** — Topology edges and neighbor lines rendered as elevated arcs via deck.gl - **GPU acceleration** — deck.gl PathLayer and IconLayer for smooth pan/zoom/tilt - **Automatic draping** — All markers and edges align to terrain elevation ### Path Visualization Clicking a packet shows its route on a map with confidence indicators: - **Green** — 100% confidence (unique prefix, no collision) - **Yellow** — 50-99% confidence (high certainty) - **Orange** — 25-49% confidence (medium certainty) - **Red** — 1-24% confidence (low certainty) - **Gray/Ghost** — Unknown prefix resolved to ghost node ## License MIT — See [LICENSE](LICENSE) ## Credits Built on the excellent work of: - **[RightUp](https://github.com/rightup)** — Creator of pyMC_Repeater, pymc_core, and the MeshCore ecosystem - **[pyMC_Repeater](https://github.com/rightup/pyMC_Repeater)** — Core repeater daemon for LoRa communication and mesh routing - **[pymc_core](https://github.com/rightup/pyMC_core)** — Underlying mesh protocol library - **[d40cht/meshcore-connectivity-analysis](https://github.com/d40cht/meshcore-connectivity-analysis)** — Viterbi HMM approach for path disambiguation and ghost node discovery - **[meshcore-bot](https://github.com/agessaman/meshcore-bot)** — Inspiration for recency scoring and dual-hop anchor disambiguation - **[MeshCore](https://meshcore.co.uk/)** — The MeshCore project and community