Mesh map · locations are anonymized — markers are approximate to about a kilometre
Roster · active window · all nodes ↗
| name | type | received | position · approx | pubkey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
⏰ Clock skew
· advert clocks running ahead · expand for the list
| node | type | clock ahead by | advert clock says | roster updated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Chat · last 24 h · rows tinted by the mesh that heard them
| when | who | mesh | message | snr | routes | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Topology graph
Busiest relays
Heard paths · click a row to trace it on the dashboard map
| node | path | heard | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Topology edges · relay a → b
| a → b | seen | last | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Clock health · every advert carries the gap between that node's clock and ours
| node | type | skew now | median | drift | samples | last heard | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Adverts · heard packets only · click a row to inspect
| received | node | type | region | skew | snr | hops | heard by | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Packet inspector · select an advert
Bad coordinates · a node's position is self-reported and nothing verifies it. These cannot be right, so they are kept off the map — and listed here so they can be fixed.
| node | type | reported position | problem | heard by | last heard | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Recent paths · !path traces reported by the mesh. Click one for the map + LOS profile
| when | who | hops resolved | length | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Multi-path runs · !mpath floods: every gateway that heard the request, each over its own route. Click one for the map
| when | who | gateways | routes | hops | state | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Run an observer · the radio your bots answer through
Observer access isn't on for this account yet. Enabling it creates your broker login, one credential for every gateway you run, and unlocks the setup below. A gateway is an openHop repeater running the txmesh plugin; here is what running one involves.
① Your MQTT login · one credential for every gateway you run
Every gateway you run signs in to txmesh with this login and publishes under its own node name. The password is stored and shown here, so set up as many nodes as you like without rotating. Only use Rotate if it leaked: every gateway using the current password stops connecting until you update its config.
② Run the gateway · an openHop repeater plus the txmesh plugin
A gateway is an openHop repeater running the openhop-txmesh-plugin. The plugin adds one more identity to the radio you already have, reports what it hears here, and transmits the replies for your !commands. Nothing to flash and no dedicated hardware.
- On openHop Repeater 1.1.4 or newer, open the Plugins page and upload the wheel from the latest release. Older repeaters, or a separate machine: follow the manual setup.
- Run openhop-txmesh keygen and add the companion below to the repeater's config.yaml with the key it prints. Restart the repeater.
- Give the plugin the settings below (the Plugins page form, or config.json) and enable it. Your node appears under Devices within a few minutes.
Full walkthrough: run an observer (this site) · plugin manager install · every setting · operations & privacy.
…
…
③ No openHop repeater? · contribute what your radio already hears
If you run meshcore-ha, the Home Assistant integration, your node can feed txmesh without an openHop repeater. Its sightings, hop chains and channel messages land in the archive, your node appears under Devices, and every path trace on the site gets sharper for it. It is data only: meshcore-ha has no way to transmit a reply, so it will not answer !commands. That still needs the plugin above.
…
Your login may only publish under meshcore/<username>/, so the first segment of both topics has to be exactly that. Anything else is refused by the broker and nothing arrives. The second segment is your node name; {PUBLIC_KEY} works there too if you would rather not pick one, at the cost of a 64-character name on the Devices page.
Nothing above has to be your route in. MeshTexas’ connect guide walks through putting a node on mqtt.meshtexas.org, whether that is flashing an ESP32 board, meshcoretomqtt on a RAK, or meshcore-packet-capture. No account needed. We subscribe to their feed, so a node set up there reaches txmesh with nothing to configure here. What you give up is ownership of it: those sightings are archived as meshtexas.org/<node>, which is analytics only: the node is not a gateway of yours, joins no mesh here, and can run no bots.
Regions · last 24 h · a repeater set with region put only forwards floods scoped to a region it holds · each node is drawn in its region's colour
Named regions · click one to list its nodes
Nodes
Mesh coverage · the Gulf region (TX · LA · MS · AL · FL), colored by the mesh that watches each county · overlaps blend · hover a county
Known meshes
All nodes · every node heard in the last 24 hours (contact cards + adverts) · click a row for the node page
| node | type | mesh | seen by | last heard | position | pubkey |
|---|
My commands · !commands that run on your observers — they fire only on traffic your gateways hear and reply through your radios
Send via my observers · transmitted as your gateway, rate-limited 6/min on-device · fleet-wide sends are admin-only
My transmissions · your sends + your commands' replies
| when | via | ch | text | source |
|---|
Site settings · what this deployment calls itself, and where it points
Stored in the database, so they outlive a redeploy. A field still on its deployment default follows the environment variable in the manifests; changing it here takes over, and Reset hands it back. Pages pick changes up within ~10 s, the collector within ~30 s.
Credentials are deliberately not editable here. The broker password, the device tokens and the database DSN stay environment variables fed from cluster secrets, so an admin account can never read them back out of a web form.
NWS active feed · live National Weather Service alerts for Texas (the same cached feed !nws and the auto-poller read) ·
| severity | event | counties | matches mesh | onset | ends |
|---|
Announcement history · warnings this system has transmitted to a mesh (NWS + river-flood), newest first
| when | kind | mesh | detail |
|---|
External data sources · analytics-only connectors: foreign MQTT brokers (meshcore-mqtt-broker packet family) or community map APIs (CoreScope, PotatoMesh) · never feed bots · changes go live within ~30s
| name | kind | url | topic / poll | regions | map | owner | msgs | last msg | last connect |
|---|
External observers · per-observer sighting stats from the sources above (packet sources appear per origin, map sources as one row)
| observer | via | region | status | last advert | adverts 24h | nodes heard |
|---|
Submit tokens · hand one to an integrator who asks: their submissions become a named sender, pre-trusted for precise coordinates · shown once, stored hashed
| label | note | issued by | issued | last used | uses |
|---|
Path senders · who's POSTing !path traces to the open submit API · tick trusted to store a sender's exact endpoint coordinates instead of the ~1 km privacy coarsening · static-token senders are always trusted · tick short links to run one sender's /p/ links through the shortener
| sender | kind | paths | first seen | last seen | last path | trusted | short links |
|---|
Origins · who has transmitted from behind a repeater · a packet's first hop is the repeater that heard the sender directly, so pick the ones around a place and see every name and radio that started there
Every lookup is logged with your name and the reason you give, and admins can read that log.
Radios · from adverts: a public key is the radio's identity, and it keeps it across every name change · positions are the newest the radio shared
| key | names advertised | type | from here | via | first | last | position |
|---|
Senders · from channel messages: a name is typed by the sender and unsigned, so it is a lead, not an identity · click a row for the messages and every route they were heard on
| sender | from here | share | via | first | last |
|---|
Lookup audit · every origin lookup ever run, newest first · admins only
| when | who | scope | repeaters | range | reason | found |
|---|
Locate · estimate where a radio is from the signal it leaves behind · gateways that heard it directly give a distance from the SNR (radios run ~22 dBm); indirect hearings place it within one hop of the repeater that relayed it first · the answer is a fuzzy area on purpose
Every lookup is logged with your name and the reason you give, and admins can read that log.
Location · when the radio reports its own position that is the answer (red pin) and the RF estimate is only a cross-check; with no report the RF estimate stands alone · shaded = RF area, faint rings are the evidence (solid = a direct hearing's distance, dashed = within one hop of a relaying repeater)
Hearing gateways · every gateway that heard this radio directly, strongest first · distance is estimated from the median SNR, and all of them (plus relayed hearings) feed the estimate, each weighted by precision
| gateway | SNR | readings | est. distance | position |
|---|
Lookup audit · every locate lookup ever run, newest first · admins only
| when | who | scope | radio | window | reason | result |
|---|
Dropped packets · adverts the collector refused at ingest · never reach the dashboard, roster, map, or any node page · after the 2026-09-17 incident with the MikeHawk / Suds observers, this is where their corruption would surface instead
Every row is an advert that validate_advert rejected before touching the archive: broken clocks (adv_ts=2, year-2105 timestamps), out-of-range positions (lat=566), control-byte names, unknown roles. Visible here, admin-only; the operator can see the pattern without any garbage leaking into live views.
| ingested | observer | reason | pubkey | name | adv_ts | skew | lat | lon |
|---|
Registered users · read-only sees data only · region manager runs one mesh's bots + sends (assign the mesh below) · admin manages users
| user | role | mesh | observer | activity | registered | last login | sessions |
|---|
Send to mesh · via the observer send bridge · sent as the gateway, rate-limited 6/min on-device
Recent transmissions · UI sends + bot replies
| when | via | ch | text | source |
|---|
Observers · every gateway we have registered, with live health (telemetry, battery, boots) · click a card for the full observer page
Inactive · no live publish for h; click to list them · they come back to the cards on their next publish · archives now, deletes
| node | owner | mesh | last seen | last telemetry | archives |
|---|
Archived · hidden from the live views; click to list them · a gateway that publishes again restores itself · removes it and clears its retained MQTT topics
| node | owner | first seen | last seen | messages | archived |
|---|
Device MQTT credentials · per-device broker logins, scoped to their own meshcore/<user>/# · password shown once
| label | username | created by | created | status |
|---|
Automated alerts · master switches for the pollers that transmit to the mesh · each mesh still needs an alert channel (and counties / gauges) below · takes effect within a minute
Meshes & alerts · one card per mesh: channels, !nws counties, auto-alert channel, !flood river gauges · public alerts page ↗
Gateway sites · group co-located gateways under one site name · commands marked one reply per gateway answer once per site per distinct RF path, so two radios in the same room don't both transmit while a gateway across the mesh still reports its own path · blank = the node stands alone
| gateway | owner | mesh | site | last message |
|---|
Core & mesh commands · shared fleet + mesh commands · via: all / mine / gateway / node
| name | kind | scope / meshes | channels | trigger | reply | via | every/cooldown | fires | last fired |
|---|
📖 reply template reference
| {sender} | who triggered the bot |
| {args} | text after the trigger prefix |
| {channel} | channel it arrived on |
| {gateway} | gateway that heard it |
| {snr} {hops} | reception SNR dB / hop count |
| {time} {date} | HH:MM UTC / YYYY-MM-DD |
| {seen NAME} | last heard age of best name match ({seen} = use {args}) |
| {whois HEX} | node names for a path-hash prefix |
| {stats} | nodes / repeaters / msgs 24h |
| {top_relays N} | busiest N relays (max 5) |
| {pathbot} | store the trigger message's RF path, reply with hops + /p/ link · silent when the request arrived direct (no relays, nothing to trace) · sends a second frame ~2s later (back-to-back the radio drops it) asking 1-byte senders to switch to 2-byte hashes, at most once a day each |
| {mpath} | the same packet as every observer heard it, on one map · acks at once, then collects for 30s (our gateways plus external sources on other meshes) and sends a second frame with an /m/ link, each route a different colour · one run per requester at a time |
| {vitals NODE} | gateway battery / uptime / rssi ({vitals} = the gateway that heard you) |
| {online} | gateway fleet status; names the down ones |
| {active N} | nodes heard in the last N hours (default 24) |
| {new_nodes N} | nodes first seen in the last N hours |
| {lastmsg NAME} | last channel message from a node + age |
| {route NAME} | how a node's advert reached us — hop chain with names |
| {skew NAME} | node clock offset vs NTP from its last advert |
| {top_talkers N} | busiest senders in 24h (max 5) |
| {lag} | sender→rx time delta of the trigger message |
| {gauge LID} | one NWPS river gauge by id, e.g. {gauge CFTT2} |
| {nws} | active NWS alerts for the mesh's counties (set per-mesh in Weather & flood alerts) |
| {flood} | river gauges at/near flood in the mesh region (NOAA NWPS) |
| {roll NdM} | dice; nest for user dice: {roll {args}} |
| {pick a|b|c} | random choice |
| {8ball} | magic 8-ball |
| {help} | list all functions |
| !ping → pong {sender}! rx {snr} dB via {gateway} | |
| !seen → {seen} · !mesh → {stats} | |