# 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 real-time web dashboard for [MeshCore](https://meshcore.co.uk/) LoRa mesh repeaters.

pyMC Console gives you full visibility into your mesh network — packet flow, topology, signal quality, RF metrics, and radio configuration — through a single browser tab. It layers on top of [pyMC_Repeater](https://github.com/rightup/pyMC_Repeater) without modifying it.

---

## Quick Start

### Requirements

- Raspberry Pi (3, 4, 5, or Zero 2 W)
- LoRa radio module (SX1262 or SX1276)
- Raspberry Pi OS (Bookworm recommended)

### Install

```bash
git clone https://github.com/dmduran12/pymc_console-dist.git pymc_console
cd pymc_console
sudo bash manage.sh install
```

During installation you'll be prompted to select a pyMC_Repeater branch — **choose `dev`** (the default). The `dev` branch has the latest features and is the recommended target.

The installer handles everything:

1. System dependencies (Python, pip, SPI tools)
2. Clones and installs [pyMC_Repeater](https://github.com/rightup/pyMC_Repeater) + [pyMC_core](https://github.com/rightup/pyMC_core)
3. Deploys the Console web dashboard
4. Configures and starts the systemd service

Once complete, open `http://<your-pi-ip>:8000` in a browser.

### Upgrade

```bash
cd pymc_console
sudo bash manage.sh upgrade
```

Choose **Console only** (updates just the dashboard) or **Full Stack** (updates Console + pyMC_Repeater + pyMC_core). Console-only upgrades are safe and fast — your repeater config is untouched.

### Uninstall

```bash
cd pymc_console
sudo bash manage.sh
```

Select **Uninstall** from the menu. Removes all installed files, config, logs, and the systemd service.

---

## How It Fits Together

```
┌─────────────────────────────────────────────────────────────┐
│                      pyMC Console                           │
│            (this repo — web dashboard UI)                   │
│                                                             │
│  • React SPA served on port 8000                            │
│  • Real-time packets, topology, stats, radio config         │
│  • manage.sh installer handles everything                   │
└─────────────────────┬───────────────────────────────────────┘
                      │ uses API from
┌─────────────────────▼───────────────────────────────────────┐
│                    pyMC_Repeater                             │
│            (RightUp's repeater daemon)                      │
│                                                             │
│  • Python daemon running the LoRa repeater                  │
│  • REST API + WebSocket on port 8000                        │
│  • Packet forwarding, logging, radio control                │
└─────────────────────┬───────────────────────────────────────┘
                      │ 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
- `manage.sh` installs both Repeater and Console side-by-side
- You can upgrade Console independently without touching Repeater

---

## Features

### Topology Analysis

Reconstructs your network's structure from packet paths using a **Viterbi HMM decoder** — resolving prefix collisions with physics-based RF constraints and real-world observation evidence.

![Topology Analysis](docs/images/analyzer-overview.gif)

- **One-click Deep Analysis** from up to 14 days of packet history
- **Viterbi HMM decoding** — resolves 2-char prefix collisions using geographic distance and LoRa range constraints
- **Ghost node discovery** — detects unknown repeaters when no known candidate fits
- **7-phase topology pipeline** — directional edges, betweenness centrality, mobile detection, TX delay recommendations, path health scoring
- **3D terrain** — AWS Terrarium elevation with hillshading; markers and edges drape onto the landscape
- **Wardriving overlay** — H3 hexagonal coverage tiles with SNR-based coloring
- **Edge confidence** — line thickness scales with observation count; color indicates certainty

### Link Quality Radar

Polar chart placing all contacts at their actual compass bearing and distance from your node.

![Link Quality Polar](docs/images/linkquality-demo.gif)

- **Zero-hop neighbors** colored by SNR (green → yellow → orange → red)
- **Multi-hop contacts** at 33% opacity to distinguish direct RF from relayed
- **Hover tooltips** with full signal metrics (RSSI, SNR, distance, last seen)

### Statistics Dashboard

Comprehensive RF metrics and network composition analysis.

![Statistics View](docs/images/statsview-expose.gif)

- **Airtime utilization** — RX/TX stacked area charts with peak and mean metrics
- **Packet type distribution** — treemap of ADVERT, TXT_MSG, ACK, TRACE, etc.
- **Network composition** — repeater / companion / room server breakdown
- **Noise floor heatmap** — interference patterns over time
- **Disambiguation health** — Viterbi confidence metrics and ghost node stats
- **TX delay recommendations** — slot-based timing optimization per node role

### Packet Path Tracing

Click any packet to visualize its route through the mesh with hop-by-hop confidence.

![Path Trace Demo](docs/images/trace-demo.gif)

- **Confidence coloring** — Green (100%), Yellow (50–99%), Orange (25–49%), Red (<25%), Gray (ghost)
- **Interactive map** showing resolved path with intermediate hops
- **Signal details** — RSSI, SNR, and timing per packet
- **Byte-level breakdown** — header fields, payload structure, raw hex

### Themes & Terminal

Two polished color schemes and a built-in CLI for direct repeater interaction.

![Themes and Terminal](docs/images/terminal-and-themes.gif)

- **Breeze Dark / Breeze Light** — KDE Breeze-inspired themes with full design token system
- **Terminal** — interactive CLI mapped to API endpoints (get/set radio, ping, diagnostics)
- **Packet capture** — `start cap` / `end cap` / `export cap` for timed diagnostic snapshots
- **Live logs** — streaming from repeater with DEBUG/INFO toggle

---

## All Pages at a Glance

| Page | Route | What it does |
|------|-------|-------------|
| **Dashboard** | `/` | Live packet counters, sparkline trends, LBT widgets, recent packets |
| **Packets** | `/packets` | Searchable packet history with detail modal, path visualization, byte breakdown |
| **Contacts** | `/contacts` | MapLibre GL map with topology edges, ghost nodes, terrain, wardriving overlay |
| **Statistics** | `/statistics` | µPlot charts — airtime, packet types, noise floor, signal scatter, network composition |
| **Mesh Graph** | `/meshgraph` | GPU-accelerated force-directed graph (Cosmograph) |
| **System** | `/system` | CPU, memory, disk, temperature, processes, network I/O |
| **Logs** | `/logs` | Live log stream with level filtering |
| **Terminal** | `/terminal` | Interactive CLI — MeshCore commands, ping, diagnostics, captures |
| **Configuration** | `/configuration` | Radio settings, TX delays, transport keys, identity, theme, stealth location |

---

## Management

### manage.sh Menu

```bash
sudo bash manage.sh
```

```
┌────────────────────────────────────────────────┐
│  pyMC Console                                  │
│  Status: Running                               │
├────────────────────────────────────────────────┤
│  install    Fresh installation                 │
│  upgrade    Upgrade existing                   │
│  uninstall  Remove everything                  │
│  status     Show versions                      │
│  logs       View live logs                     │
│  exit       Exit                               │
└────────────────────────────────────────────────┘
```

- **Install** — Full Stack or Console-only
- **Upgrade** — Console-only (fast, safe) or Full Stack (Console + Repeater + Core)
- **Uninstall** — Removes everything (installation, config, logs, service)
- **Status** — Installed versions of Core, Repeater, Console
- **Logs** — Live journal output from the repeater

### Radio & GPIO Configuration

Radio and GPIO settings are managed by upstream pyMC_Repeater:

```bash
cd ~/pyMC_Repeater && sudo ./manage.sh
```

Or edit the config directly:

```yaml
# /etc/pymc_repeater/config.yaml
radio:
  frequency: 927875000      # Hz
  spreading_factor: 7       # SF7–SF12
  bandwidth: 62500          # Hz
  tx_power: 28              # dBm
  coding_rate: 6            # 4/5, 4/6, 4/7, 4/8
```

> You can also change radio settings live from the **Configuration** page in the dashboard — no SSH required.

### DIO2 / DIO3 Pin Configuration

Some LoRa modules need specific DIO pin settings. These are **independent** — enabling one does not affect the other:

- **DIO3 (TCXO)** — set `use_dio3_tcxo: true` if your module has a temperature-compensated oscillator on DIO3
- **DIO2 (RF Switch)** — set `use_dio2_rf: true` if your module uses DIO2 for TX/RX antenna switching

```yaml
radio:
  use_dio3_tcxo: true
  use_dio2_rf: true       # dev branch only
```

### Service Management

```bash
sudo systemctl status pymc-repeater     # Check status
sudo systemctl restart pymc-repeater    # Restart
sudo journalctl -u pymc-repeater -f     # Live logs
```

---

## Directory Layout

After installation:

```
~/pymc_console/               ← This repo (cloned by you)
~/pyMC_Repeater/              ← Repeater daemon (cloned by manage.sh)

/opt/pymc_repeater/           ← Installed repeater
/opt/pymc_console/web/html/   ← Installed dashboard
/etc/pymc_repeater/config.yaml ← Radio + repeater configuration
/var/log/pymc_repeater/       ← Log files
```

---

## Hardware

### Supported Boards

- Raspberry Pi 3, 4, 5
- Raspberry Pi Zero 2 W
- Any SBC with SPI and GPIO (untested but likely works)

### Tested Radio Modules

- Waveshare SX1262 HAT
- Ebyte E22 modules
- LILYGO T3S3 (via USB serial)
- Heltec LoRa 32

### Connection

LoRa module connects via **SPI** with GPIO pins for reset, busy, and DIO1. Pin mapping is configured during installation via pyMC_Repeater's manage.sh.

---

## Troubleshooting

### Dashboard won't load

1. **Is the service running?**
   ```bash
   sudo systemctl status pymc-repeater
   ```
2. **Is port 8000 responding?**
   ```bash
   curl -s http://localhost:8000/api/stats | head -c 100
   ```
3. **Check for errors:**
   ```bash
   sudo journalctl -u pymc-repeater -n 50
   ```

### Login fails / "Error 200"

Usually caused by a version mismatch between Console and Repeater.

```bash
cd pymc_console
sudo bash manage.sh upgrade
```

Select **Full pyMC Stack** to update everything to compatible versions.

### No packets being received

1. **SPI enabled?**
   ```bash
   ls /dev/spidev*
   ```
   If no devices listed, enable SPI via `raspi-config` → Interface Options → SPI.

2. **GPIO correct?** Run pyMC_Repeater's manage.sh → Configure GPIO and verify pin assignments match your wiring.

3. **Frequency match?** Confirm your radio frequency matches the rest of your mesh network.

4. **Check the logs:**
   ```bash
   sudo journalctl -u pymc-repeater -n 100 | grep -i "error\|fail\|radio"
   ```

### Service won't start

```bash
# Check for config syntax errors
python3 -c "import yaml; yaml.safe_load(open('/etc/pymc_repeater/config.yaml'))"

# Check for Python dependency issues
pip3 show pymc-repeater pymc-core
```

### "Radio presets file not found" during install

Non-fatal warning. The installer fetches presets from an API; if unavailable, it falls back to common defaults. Installation continues normally.

### Dashboard loads but shows no data

- The dashboard requires authentication. If you see the login page, use the credentials you set during pyMC_Repeater installation.
- If you're on a fresh install, allow 30–60 seconds for the repeater to initialize and begin receiving packets.
- Check that WebSocket is connecting: open browser DevTools → Network → WS. You should see an active `/ws/packets` connection.

### Upgrade didn't take effect

Hard-refresh your browser (`Cmd+Shift+R` / `Ctrl+Shift+R`) to clear the cached SPA bundle. Vite hashes filenames, but the browser may still cache `index.html`.

---

## Under the Hood

### Viterbi Path Disambiguation

MeshCore packets contain 2-character hex prefixes representing the route through the mesh:

```
Path: ["FA", "79", "24", "19"]
       Origin → Hop1 → Hop2 → Local
```

Multiple nodes can share the same 2-char prefix (1-in-256 collision). The system uses a **Viterbi HMM decoder** to find the most probable sequence of actual nodes:

- **States** — all candidate nodes matching each prefix, plus a "ghost" state for unknowns
- **Priors** — recency-weighted (recently-seen nodes are more likely)
- **Transitions** — physics-based costs using geographic distance and LoRa range constraints
- **Key principle** — when edge observations have ≥80% confidence, real-world evidence overrides physics

Before Viterbi decoding, candidates are scored using **four-factor analysis**:

1. **Position (15%)** — typical path positions for this prefix
2. **Co-occurrence (15%)** — which prefixes appear adjacent
3. **Geographic (35%)** — distance to dual-hop anchor points
4. **Recency (35%)** — exponential decay `e^(-hours/12)`

### Ghost Node Discovery

When no known candidate is geographically plausible, the decoder selects a "ghost" state. These are clustered and classified into four tiers:

- **Confirmed** — very high observation count, consistent neighbors, plausible location
- **Likely** — strong evidence, probably a real undiscovered repeater
- **Possible** — moderate evidence, worth investigating
- **Noise** — low evidence, likely path artifacts

Ghost clusters include RF-constrained location estimates, temporal consistency analysis, and collision detection against known nodes.

### 7-Phase Topology Pipeline

1. **Directional edge tracking** — forward/reverse counts, symmetry ratio
2. **Path sequence registry** — all observed paths, canonical detection
3. **Flood vs direct classification** — per-edge routing type
4. **Edge betweenness centrality** — backbone identification
5. **Mobile repeater detection** — path volatility analysis
6. **TX delay recommendations** — slot-based timing optimization
7. **Path health scoring** — combined health, weakest link, latency

### Protocol Library

The frontend includes a complete TypeScript port of the MeshCore protocol — binary packet parsing, header bit-field extraction, per-type payload decoders, channel key derivation, and GRP_TXT decryption (SHA-256, AES-ECB, pure JS — no native dependencies).

---

## Standalone UI Installation

If you already have pyMC_Repeater running and just want the dashboard, see [INSTALL.md](INSTALL.md) for manual tar.gz installation without manage.sh.

---

## License

MIT — See [LICENSE](LICENSE)

## Credits

Built on the work of:

- **[RightUp](https://github.com/rightup)** — Creator of pyMC_Repeater, pymc_core, and the MeshCore Python ecosystem
- **[pyMC_Repeater](https://github.com/rightup/pyMC_Repeater)** — Core repeater daemon
- **[pymc_core](https://github.com/rightup/pyMC_core)** — Protocol library
- **[MeshCore](https://meshcore.co.uk/)** — The MeshCore project and community
- **[d40cht/meshcore-connectivity-analysis](https://github.com/d40cht/meshcore-connectivity-analysis)** — Viterbi HMM approach for path disambiguation
- **[meshcore-bot](https://github.com/agessaman/meshcore-bot)** — Recency scoring and dual-hop anchor disambiguation
