Bound OTA-over-LoRa duty cycle across repeaters with one runtime-tunable,
persisted limit (OtaManager::max_hops, `ota config hops <0..8>`, default 3):
- Accept-gate: a node ignores OTA that arrived from more than max_hops hops
away (neither processes nor relays it). 0 = direct only.
- Forward-cap: relay a flood only while still under max_hops, appending this
node's path-hash (hop count increments like the mesh flood routing).
- RAM guard: relay an OTA flood only while more than OTA_FWD_MIN_FREE packet-
pool slots stay free, so heavy OTA (best-effort, lowest-priority) can never
monopolise the shared pool and starve real traffic — a dropped relay is
re-requested by the source.
Persisted in NodePrefs (CommonCLI) and shown in `ota config`. Docs updated.
The discovery beacon previously re-announced at a random 3-10 min interval.
Replace that with a fixed, user-configurable cadence:
- OtaManager::advert_mins() — re-advertise every N minutes after the boot
burst; 0 disables periodic re-advertise (boot burst only). Default 24h.
- Persisted in NodePrefs (CommonCLI) and runtime-tunable: `ota config advert
<minutes>` (0..10080; 0 = off), and shown in `ota config`.
- When periodic advert is disabled, the scheduler still re-checks the config
on a slow timer, so a later `ota config advert <mins>` takes effect live.
Also advertise immediately whenever the served set changes — when a motatool
folder is attached to / detached from the ESP32 WiFi seeder — so peers learn
about newly-available firmware without waiting for the next interval (the
`ota folder` serial path already announced on attach).
Docs: protocol beacon-cadence note + user-guide `ota config advert`.
Extends the USB-serial folder relay to WiFi so an ESP32 companion can both
serve .mota and be operated headlessly:
- motatool `serve --tcp <host[:port]>`: a TcpTransport sibling of the serial
transport (default port 5001). SeederCore/Folder are reused unchanged — the
COUNT/DESCRIBE/READ protocol is transport-agnostic.
- ESP32 companion: a dedicated OTA seeder port (5001) for `serve --tcp`, plus
an OTA text console on 5002 (`nc <ip> 5002` -> `ota status|ls|announce|...`,
the same handle_ota_command CLI serial nodes have). Both run alongside the
phone-app port (5000); all three coexist.
- WiFi.setSleep(false): ESP32 STA mode's modem power-save periodically sleeps
the modem/CPU and stalls the SX1262 SPI+DIO servicing, leaving LoRa deaf
while WiFi is associated. Disabling it restores the radio (HW-validated:
a V3 WiFi companion is then discovered over LoRa and discovers its peers).
- docs: serving .mota over WiFi (protocol §10.2 + user guide).
Extract the inline cursor-walk in handleRegionCmd into file-local
helpers (skipSpaces, rtrimSpaces, takeToken, splitNameJump,
processRegionDefSegment), grouped immediately above the consumer.
Behavior is identical; addresses PR #2540 review feedback on
readability.
Tighten the region def docs: collapse five Note callouts into three
grouped paragraphs (Behavior / Existing regions / Limits), add a
case-sensitivity caveat plus an error example, note the cursor reset
between split commands, and use generic placeholder names.
Add a new command `region bulk` for defining region hierarchies in a single line. This command allows users to create multiple regions in a single message. Updated the documentation to include usage examples and detailed parameter descriptions.