Operate a node
Understand what the shared radio reports, which role owns which identity, what a restart keeps, and how to administer and watch a running node.
Shared radio and airtime
The shared modem owns tuning, channel access and the transmit queue. It hands every received packet to each role and schedules their outgoing packets against shared capacity and airtime limits. The selected image sets how many roles and KISS connections it accepts.
| Status | Meaning | What to do |
|---|---|---|
| Queued | The modem accepted the packet and is waiting for airtime. | Wait for a result. |
| Confirmed | The radio sent the packet. | Look for a recipient ACK or reply to confirm delivery. |
| Uncertain | The connection or modem failed before a result arrived; the packet may or may not have been sent. | Check status before sending again. Uncertain packets are not replayed automatically after reconnecting. |
Local reflections: when one role transmits, the other roles on the same node receive a copy marked as a local reflection. It is labelled apart from RF receptions, which carry measured RSSI and SNR, and does not show that any other radio heard the packet.
Adaptive bot admission (opt-in) reduces bot work as local RF load and queues grow, sharing the allowance fairly among callers. Enable it through owner administration and restart; bot adaptive reports the saved setting and live load. On a host, use adaptive on the owner socket.
A second repeater on the same mesh can duplicate forwarding and use extra airtime. Place repeaters deliberately.
RF load and capacity measurements: received replies, room delivery, queues, airtime and memory during mixed traffic.
Roles and identities
Each role is a separate MeshCore node with its own key. A standalone ESP32 runs one of each built-in role; a Go host can run additional instances. Pine pairs its repeater with the Lua bot.
| Role | Owns | Notes |
|---|---|---|
| Shared modem | Tuning, channel access, transmit queue and airtime | Holds no role keys. |
| Repeater | Its key and settings | Forwards eligible RF traffic. |
| Room | Its key, login policy, members and recent history | Room passwords are separate from administrator passwords. |
| Companion (Base) | Its key, contacts, channels and messages | Every app on this endpoint shares the identity. Uses companion protocol 13. |
| Command bot | Its key, installed program and stored data | Separate from the Base and from any external bot. |
| Management | Node-wide administration and radio settings (ESP32) | Role administrator access does not grant it. |
| Observer | Its key, for publishing RF receptions to MQTT | Role metadata stays on separate topics. |
Names and role settings change without rebuilding. Changing an identity needs owner authority, and private data stays tied to the full key that created it. The MeshCore Android app connects over WiFi TCP, exchanges direct and room messages, and administers repeater and room roles you are authorized for.
What survives a restart
Kept
- Role keys and saved settings
- Installed bot programs and the previous version for rollback
- Stored data for each caller, conversation, channel and bot
- Timers and reminder records
Starts fresh
- Lua global variables and running jobs
- Contacts and routes the bot learned in memory; advertise again to restore them
- Pine's trusted time and BLE pairings
Stored data stays with the full identities it belongs to, through name and program changes. Rolling back a program changes the code and leaves stored data and timer claims as they are.
Each reminder can be sent at most once. Restoring a backup does not re-arm reminders that were already sent or whose send was uncertain. A pending reminder needs trusted time and a fresh route, and expires after a 60-second delivery window.
The Xiao_S3_WIO_onchip_bot image runs custom programs from RAM; the bundled program returns after restart. Use the managed (_beta or _https) images for installed programs that persist.
Administer a node
Over LoRa: open Management, install a command and use admin controls
| Node | Where | Start with |
|---|---|---|
| Standalone ESP32 | Authenticated RF Management, or http://NODE_IP/admin on a trusted LAN | Roles, Shared radio and Programs sections |
| Go host | Owner Unix socket on the host, or host browser administration | http://127.0.0.1:9080/status |
| Willow Hew host | Owner-only owner.sock and admin.sock; separate native dashboard | python3 -B willow.py health --state /path/to/private/willow |
| Pine | Pine-Relay's administrator console in the MeshCore app, over RF | bot status, bot limits, source status |
Aspen controls cover role selection, names, radio settings, grants, program installation, rollback and scoped backups. Program transfers over RF can resume through ordinary MeshCore repeaters. Willow's local controls cover its supported role and bot settings, not shared modem tuning; consult its service guide before a change.
- Check before rebooting. Compare saved and applied settings first. A radio change affects every role on that modem.
- After a timeout, read status before repeating an install or restore; the first request may have completed.
- Before maintenance, keep program and scoped data backups. Use the platform's recovery procedure for an unreadable filesystem rather than reprovisioning it.
Keep local services private. KISS, companion TCP and the ESP32 dashboard and /admin page use plain HTTP or TCP, so credentials and backups are visible to anyone on that network. Use them on a trusted LAN or protected tunnel, and import secrets over encrypted RF or the host's owner socket. Plain MQTT also needs a trusted network.
RF management and owner CLI · ESP32 browser administration · Go host status and owner socket · Willow service and owner controls
Watch the traffic
The observer publishes RF receptions to your MQTT broker as observer-v1 messages with upstream-compatible packet fields and hashes. Packets and status use meshcore/IATA/UPPERCASE_OBSERVER_KEY/{packets,status}; role metadata uses separate lowercase-key topics.
- The packet feed contains RF receptions only. Local transmissions and reflections are kept separate.
- Aspen publishes with QoS 0 and a bounded queue. Go and Willow host observers use QoS 1; broker acknowledgement confirms publication, not subscriber processing. Host retries can redeliver a packet, and in-memory queued observations are lost when their owning process or queue restarts.
- Connect over MQTT on a trusted LAN, or WSS with CA and hostname checks. Send packets only to a broker you trust with your traffic.
- MQTT is off in the public Aspen setup profile; configure it in a source build.
- Willow's observer currently accepts loopback brokers and
mqtt-meshcore-1.ve6slp.caonly. Check its endpoint and authentication settings before choosing a broker; the Go host and Aspen have separate configuration contracts.
The KISS monitor decodes serial or TCP traffic, and the node dashboard shows roles, connections, queues, airtime and memory. For history, import the Grafana dashboard and select your Prometheus data source; the ESP32 telemetry publisher feeds resource panels and a companion bot can poll traffic and repeater status.
Aspen observer setup · Willow observer setup · Grafana dashboard import · Dashboard JSON
Operating Pine
Pine runs the shared Lua engine beside a native repeater, with separate repeater and bot identities. It supports custom commands, personal notes, stored data, events, timers and mesh operations.
- Limits: two Lua job slots (at most one for custom or event work, so built-in commands keep capacity), 4,096-byte programs and a 48 KiB Lua memory quota. Check
bot limitsbefore installing a program. - Trusted time: after each restart, an authenticated administrator sends
bot time UNIX_SECONDS, and refreshes it at least hourly. Reminders and other deadlines wait in storage until time is set. - Radio counters:
bot radioshows queued, confirmed and failed or uncertain transmissions and RF time. - BLE (optional): a MeshCore companion app can pair over BLE as Pine-Bot, using a locally set six-digit PIN. Pairings clear on restart; forget the old pairing on the phone and pair again. Pairing does not grant repeater administration.
ESP32 memory and flash
The combined node needs an ESP32-S3 with 8 MiB flash and PSRAM. Each application slot holds 3,342,336 bytes.
- Lua has a 96 KiB memory cap per program state.
- Wasm reserves a 1 MiB PSRAM interpreter pool on first use, kept until restart, plus 64 KiB of program memory per instance.
- The radio, WiFi, TLS and task stacks also need internal RAM.