how to configure a fleet of independent RP's to observe packets moving over a meshcore network
  • Shell 53.6%
  • Python 46.4%
Find a file
douwe schmidt cc747082be Initial commit: Mesh Observer Fleet toolkit
Generalised toolkit to build, deploy and analyse a fleet of passive LoRa
(MeshCore) observer kits: Raspberry Pi + SenseCAP T1000 listen-only radios
that log every overheard packet for offline coverage/route analysis.

Includes Pi-side scripts (capture, scheduled frequency switch, heartbeat),
systemd units, a read-only laptop fleet health-check, an analysis skeleton,
and full build/deploy/operate docs (docs/01-08).

Secrets and personal data removed; configuration via .env / kits.conf.
2026-06-18 10:25:35 +02:00
analysis Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
docs Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
scripts Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
systemd Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
.env.example Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
.gitignore Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
LICENSE Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00
README.md Initial commit: Mesh Observer Fleet toolkit 2026-06-18 10:25:35 +02:00

Mesh Observer Fleet

A toolkit for measuring how a LoRa mesh network actually performs in the field, using a fleet of cheap passive observer kits — a Raspberry Pi + a SenseCAP T1000 radio in listen-only firmware — that log every overheard packet (RSSI, SNR, message hash, route) to disk for offline analysis.

It covers the whole chain: build one observer, mass-produce the fleet from a golden image, deploy and health-check them, switch the radio frequency mid-test on a schedule (no SSH needed), then merge and analyse the logs.

Origin & status. Built for a real 6-kit MeshCore emergency-communication pilot in a Dutch city. It has been generalised: deployment specifics (locations, people, passwords, keys, device MACs) were removed and replaced with placeholders, so this is a reusable template rather than a turnkey config. The analyse_observer.py analysis is a working skeleton — see docs/07-analysis.md.

Why this exists

Mesh radios don't keep a usable log of network behaviour. To answer "did the network carry itself?" with evidence you need independent listeners at the points that matter, each recording every packet. A key method here is the two-block test: run first on a shared community frequency, then switch the whole fleet to an isolated frequency, so you can separate "my network relayed it" from "the ambient mesh relayed it for me." Full reasoning in docs/01-architecture.md.

   LoRa packets  ──►  T1000 (companion FW, RX only)  ──BLE──►  Raspberry Pi  ──►  JSON log on SD
                                                                  (powerbank)
        × N observers at the sites that matter  ──►  collect & merge  ──►  coverage / RSSI / routes

Hardware per kit

  • Seeed SenseCAP T1000-E flashed to MeshCore Companion (Bluetooth) firmware
  • Raspberry Pi Zero W v1 (or any single SBC with BLE+WiFi — keep the whole fleet on one architecture)
  • 20 Ah+ powerbank, microSD, USB-C + micro-USB cables

Details and the ARMv6/clock caveats: docs/02-hardware.md.

Quick start

Work through the docs in order:

  1. 01 — Architecture & rationale
  2. 02 — Hardware
  3. 03 — Build one observer end-to-end
  4. 04 — Golden image & fleet
  5. 05 — The scheduled frequency switch
  6. 06 — Field deployment & operations
  7. 07 — Analysis
  8. 08 — Lessons & pitfalls ← read this early

Repo layout

README.md
LICENSE                 GNU AGPL-3.0
.env.example            secrets/config you must supply (channel key, target freq, …)
.gitignore              keeps secrets, logs and captured data out of git
docs/                   0108, the full build-and-operate guide
scripts/                Pi-side scripts + laptop fleet health-check
  run-capture.sh          unique-file-per-session capture w/ BLE pre-disconnect fix
  switch_freq.py          set_radio + reboot (reads MAC from .env.local)
  switch-frequency.sh     robust scheduled switch wrapper (retry + guaranteed restart)
  heartbeat.sh            per-minute liveness stamp
  check_all_pis.sh        read-only PASS/WARN/FAIL fleet check from your laptop
  kits.conf.example       per-fleet config for the health-check
systemd/                meshcore-capture / switch (.service+.timer) / rfkill-unblock
analysis/
  analyse_observer.py     merge logs, heard-matrix, coverage, reception % (skeleton)
  requirements.txt

Security & privacy

This repo is built to be safe to publish:

  • No secrets are committed. WiFi passwords, the AES-128 channel key and device MACs live in .env / .env.local / scripts/kits.conf (all git-ignored). Copy .env.example and scripts/kits.conf.example and fill in your own. The MeshCore #Public default key is a well-known public constant and is the only key left in code.
  • No personal data. Volunteer names, contacts and exact GPS coordinates from the original deployment were removed; PREFIX_MAP in the analysis uses example placeholders.
  • If you fork this for a real deployment, keep your real keys/locations out of git — git history is permanent.

Credits & dependencies

License

GNU Affero General Public License v3.0 — see LICENSE. You are free to use, study, share and modify this; derivatives (including networked services) must stay under the same license.