mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-11-04 11:57:16 +00:00
Real-time was three equal panels (commands, packets, messages) that each scrolled on their own, couldn't be held still, and showed the same transmission up to three times. It's now one tape with one row per transmission: a packet, the channel message decrypted from it and a command it triggered share a row, joined by packet hash, and the bot's reply hangs under the command with how many times a repeater was heard echoing it. Those echoes fold into the reply instead of getting rows of their own, and a packet heard several times is one row with a count and every reception (SNR, RSSI, hops, path) when opened. A receiver strip at the top says whether the bot is listening or the radio is offline or not responding (from the banner poll base.html already runs, now published as a banner-status event), when it last heard a packet, the packet rate and a 10-minute activity bar. The tape holds still while you read it: Pause (P), scrolling down, a moving mouse pointer or keyboard focus queue new rows behind an "N new" button. Rows can be kept (safe from the 300-row limit and from Clear), filtered to messages or commands, by packet type or channel, and searched (/). Replayed history sits under a "Heard before you opened this page" divider, and adverts and keyed group text are decoded in the browser and labeled as such. Each row's glyph chip carries its packet type's icon in the dashboard chart's color for that type; decoded messages get a stronger tint, and the bot's commands and replies are violet. Server side, command rows carry trigger_packet_hash (from the message's routing info) and, once the transmission tracker matches a repeat, reply_packet_hash. Replayed rows carry stream_ts and replayed, and live rows stream_ts. Commands stored before this pair with their message only on an exact sender, channel and text match within 20 seconds. Real-time is admin-only now: its socket already was, so anonymous visitors got three "Admin login required" badges over spinners that never filled. They're redirected to login and the nav link is hidden from them. The byte breakdown sliced multibyte paths by hop count, so 2- and 3-byte hops spilled into the payload; it uses the path's byte count and shows the raw path-length byte. Route types 0 and 2 were swapped, and the channel key store was often built before the decoder had loaded, so it never decrypted anything. js-sha256 is vendored under static/vendor instead of loading from cdnjs.
5.1 KiB
5.1 KiB
Product
Platform
web
Users
- Bot operators at a desk. The person who runs a meshcore-bot instance, usually a self-hoster on their own LAN, checking health, digging into the mesh, and changing settings from a laptop.
- Bot operators on a phone. The same operators checking in away from the desk. Phone use is a real workflow, not an afterthought; every page an operator needs has to work properly at phone width.
- Mesh community, read-only. Neighbors on the local mesh who are given the URL. When a
web_viewer_passwordis set, anonymous visitors can still reach the public pages (dashboard, contacts, mesh graph) and the anonymous-safe APIs behind them; everything else redirects to login. With no password the whole viewer is open (legacy mode).
Product Purpose
The web viewer is the browser front end for a MeshCore Bot: a Python bot that connects to a MeshCore LoRa mesh over serial, BLE, or TCP and answers commands, runs scheduled messages, and provides data services. The viewer exists so an operator can see and run the bot without a terminal or hand-editing config.ini, and so the community can see what the bot sees of the mesh.
Four jobs, all first-class:
- Is the bot healthy? Radio connected, recent activity, errors, uptime: a glance and done.
- Understand the mesh. Contacts, the mesh graph, paths, multibyte rollout, region warnings: who is out there and how packets travel.
- Watch live traffic. Realtime packets and logs while debugging or testing on air.
- Configure the bot. Plugins, feeds, schedule, greeter, radio, and config from the browser, with changes validated and written back to
config.ini.
Positioning
The viewer sees the mesh from the bot's own radio. Its data is what this node actually heard (adverts, paths, SNR, observed hops), recorded over time in the bot's database, and its settings act on a live bot and radio. Mesh-wide maps and analyzers aggregate many observers; this is one station's ground truth plus the controls for that station.
Operating Context
- Served by Flask from inside the bot process (or standalone via
python3 -m modules.web_viewer.app), default on the LAN, optionally behind a reverse proxy with HTTPS and auth. - Live updates over Socket.IO (realtime packets, logs, status).
- Optional single admin password (
web_viewer_passwordin[Web_Viewer]); there is no per-user account system. - Settings writes go to
config.iniwith comments preserved and a timestamped backup; command settings hot-reload, service on/off needs a restart. - Some features are opt-in and their pages only appear when enabled (for example the multibyte monitor).
Capabilities and Constraints
- Low-power hosts. The bot often runs on a Raspberry Pi, down to a Pi 2. Pages, queries, and polling have to stay light on the server and the client.
- Works without internet. The viewer may run on a LAN with no internet access. The map and graph libraries (Leaflet, MapLibre, vis-network) and the login fonts are vendored under
static/. Bootstrap, Font Awesome, Socket.IO, Chart.js and js-sha256 still load from public CDNs, which breaks that requirement; new work must not add CDN-only dependencies, and vendoring those is an open task. Map tiles come from OpenStreetMap and OpenFreeMap and need internet by nature. - Light and dark themes. Both are supported today (system preference plus a manual toggle) and both must keep working.
- Undecided: whether to stay on Bootstrap 5 and whether to keep the viewer free of a frontend build step. Neither is a commitment; the current implementation uses server-rendered Jinja templates, inline and static CSS/JS, and Bootstrap 5.1.3.
- Terminology: MeshCore terms (repeater, companion, room server, advert, path, hop, prefix, multibyte, region, scope, channel) are used as the firmware and community use them.
Brand Commitments
- The navbar brand is the operator's configured
bot_name, falling back to "MeshCore Bot". The viewer belongs to whoever runs it, not to a product brand. - The project's own voice is cautious about airtime: it discourages adding bots to a mesh that doesn't need them and defaults costly features (like neighbor discovery) to off.
Evidence on Hand
- Real data comes from the operator's own bot database (
meshcore_bot.db) and live radio. There are no sample datasets, testimonials, or usage metrics, and none should be invented. - Docs:
docs/web-viewer.mdand the per-feature pages underdocs/.
Product Principles
- Ground truth over guesses. Show what this radio observed, and be honest about provenance and uncertainty; never present inferred mesh data as confirmed.
- Glance first, depth on demand. Health should be readable in seconds, with the detailed mesh and traffic views a click away.
- Every operator job works on a phone.
- Respect the host and the air. Light pages, light polling, nothing that quietly costs Pi CPU or mesh airtime.
- Public views stay safe. Anything shown to anonymous visitors is mesh-visible or aggregate data only: no channel keys, config, logs, or private messages.