Commit Graph
5219 Commits
Author SHA1 Message Date
Valentin Kivachuk Burda cbdc629f20 docs: clarify the warm-start capture workflow (--seed flag + validate switch)
Spell out how the warm-start seed is actually applied (a user asked): the seed is the --seed <file> given to `motatool serve`, NOT a file dropped into the --dir destination (which starts empty). motatool stamps that one seed into the fresh .part on every `… folder validate` begin, so it's always the named file — no guessing. `validate` is the switch (a plain folder pull fetches from 0); a re-pull re-begins fresh (never resumes a stale partial); a mismatched/absent seed just falls back to fetching those blocks over the radio (correct result, only slower).
2026-07-03 08:16:56 +02:00
Valentin Kivachuk Burda 0319a81d69 ota: stamp the real FIRMWARE_VERSION into the EndF trailer (was v0.0.0)
The EndF post-build stamper read the version via _cppdef('FIRMWARE_VERSION'), which only sees -D build flags — but MeshCore authors FIRMWARE_VERSION as a header #define in each example, so the stamper found nothing and defaulted fw_version to 0. Every .mota / OTA advert then reported v0.0.0 while `ver` (which reads the header at runtime) showed the real version.

Read the header value as a fallback WITHOUT moving where MeshCore authors it: honor a -D override first (the header's #ifndef guard invites it, for release builds), else read the #define from the example this env builds (via build_src_filter), falling back to the repo-wide value when unambiguous. Purely additive to our own EndF tooling — no MeshCore source changed.

HW-verified: RAK4631 now reports `fw v1.17.0` in ota stats/ls (was v0.0.0), matching `ver`.
2026-07-03 08:02:59 +02:00
Valentin Kivachuk Burda b159737ede ota: admin OTA statistics — ota stats reply
Add an admin-only `ota stats` reply: one dense line with the running firmware's merkle content-id (mid) AND its EndF body_hash (only body_hash was surfaced before), version, served-set count + digest, live fetch state/progress, and policy — snprintf-bounded to the 160-byte reply. The remote CLI path is already admin-gated, so it's admin-only over the mesh (send it from the app's repeater command screen, or the WiFi/serial OTA console). A new servedDigest() accessor exposes the beacon set-digest.

HW-verified on RAK4631: reports the fw identity + live fetch state (incl. during a warm-start capture).
2026-07-03 08:02:37 +02:00
Liam Cottle acdf4e5bdc Merge pull request #2372 from jirogit/fix/region-save-return-value
fix(RegionMap): save() returns actual write success instead of hardcoded true
2026-07-03 12:40:22 +12:00
mikecarper e8a2f9a4d5 Disable companion auto-add in cascade 2026-07-02 10:57:46 -07:00
Valentin Kivachuk Burda 8953214761 ota: fragment-level want_mask requests (anti-burst) + warm-start leaf-diff capture
Protocol: OTA_REQ and OTA_GET_MANIFEST now carry a want_mask bitmap, so a fetcher asks for specific fragments (all on the first request, only the still-missing holes on a retry) instead of a whole block/manifest window. The WANT_MANIFEST and FETCHING retry loops re-ask only on a no-progress tick, so a lost fragment costs one fragment to recover and a re-request can't collide with an in-flight multi-fragment burst on half-duplex radios.

Warm-start (motatool folder-capture only): new OTA_GET_LEAVES/OTA_LEAVES let `ota pull <#> folder validate` bulk-fetch the target's merkle leaves, authenticate them against the manifest root, diff a similar seed build already staged in the destination, and pull DATA over LoRa only for the blocks that differ. Leaves are bitmap-fragmented + no-progress retry-gated like the manifest, capped at OTA_DIFF_MAX_BLOCKS so the want_mask stays a fixed uint16, and the diff runs a bounded batch per loop tick so it never starves the mesh loop. motatool `serve --seed <build.mota>` injects the seed payload into the destination .part on OP_BEGIN.
2026-07-02 19:03:28 +02:00
Valentin Kivachuk Burda 4a601486ac ota: nRF52 mOTA flash-layout safety net + tests
Route both begin() and reopen() through a pure mota_nrf52_stage_plan() that bottom-aligns a received .mota below the filesystem region (trailer ending at FS_START, where the bootloader scans) and refuses any size that would overrun that ceiling or overlap the running image — the single place the FS/prefs-safe bounds are enforced. Add compile-time static_asserts pinning the flash-layout ordering (app < staging ceiling < bootloader; in-place workspace ends at/below the ceiling) so an inconsistent constant fails the build instead of silently corrupting user prefs. Cover the pure planner in test/test_ota/test_ota_flashplan.cpp.
2026-07-02 19:03:06 +02:00
me 5de6512090 fix(techo-lite): remove unused EXTERNAL_FLASH_DEVICES definition entirely
Per review feedback from @liamcottle and @entr0p1, EXTERNAL_FLASH_DEVICES
is not used by MeshCore firmware — CustomLFS determines the flash chip
via JEDEC ID at runtime instead. Removing the definition entirely rather
than keeping the (now-confirmed-unnecessary) correct value.

Also removes EXTERNAL_FLASH_USE_QSPI, which was paired with the same
define.
2026-07-02 08:43:06 -07:00
me 4866268cb9 fix(techo-lite): remove duplicate EXTERNAL_FLASH_DEVICES definition
variant.h defines EXTERNAL_FLASH_DEVICES twice:
- First (correct):    ZD25WQ32CEIGR (32Mbit = 4MB, matches actual hardware)
- Second (incorrect): MX25R1635F    (16Mbit = 2MB, T-Echo non-Lite chip)

Due to C preprocessor behavior, the second definition silently overrides
the first, causing firmware to initialize the wrong flash chip. This can
result in LittleFS operating incorrectly on T-Echo Lite hardware.

Remove the erroneous second definition.

Also fix missing newline at end of file.
2026-07-02 08:28:01 -07:00
ripplebiz 33fdf67e4d Merge pull request #2874 from neilalexander/neil/replyregion
Fix `recv_pkt_region` incorrect usage
2026-07-02 22:20:30 +10:00
Neil Alexander 0d7379520f Fix recv_pkt_region incorrect usage
The `recv_pkt_region` is set when processing a flood packet in `filterRecvFloodPacket`
but direct/non-flood packets would never pass through that function, so the pointer was
not cleared for them.

`sendFloodReply` would then later use it blindly, which meant that the response would
either inherit the region from the last flood packet, or refer to a non-initialised pointer
if no region floods had been received yet.
2026-07-02 09:28:41 +01:00
Valentin Kivachuk Burda 49820b57aa docs: pull a firmware .mota off the mesh into a motatool folder
Document `ota pull <#> <dest>` (flash|folder, destination mandatory), the folder
pull that captures a device's exact firmware to the host as <mid>.mota (for
delta-building), the paused/resume-on-reconnect behaviour, and that a `motatool
serve` link doubles as the pull-to-folder store. (protocol §10, user guide,
motatool README)
2026-07-02 08:52:40 +02:00
Valentin Kivachuk Burda 28e3df02f9 ota: pause a folder pull on link loss, resume + rescan on reconnect
If an `ota pull <#> folder` block-write fails mid-transfer (the motatool seeder
link dropped), the fetch enters a new PAUSED state instead of failing or falling
back to RAM/flash: progress stays on the host, the manager stops requesting, and
loop()/stall-detection leave it untouched (it waits indefinitely). On reconnect
the ESP32 seeder re-registers the folder destination and, if PAUSED, calls
resumeStaged(): OP_STAT re-attaches the host's partial, the leaves are re-read,
and only the missing blocks are re-requested (a brand-new/absent file restarts
from 0). `ota status` reports the paused state.
2026-07-02 08:50:20 +02:00
Valentin Kivachuk Burda 10fa434412 ota: pull a fetched .mota to a host folder (ota pull <#> folder) — firmware side
FolderMotaStore: an OtaStore that streams an in-transit .mota straight to the host
folder over the seeder link (OP_BEGIN/WRITE/SREAD/STAT/FIN) instead of RAM/flash —
the device holds no local staging for it. Wired as a selectable pull destination:

- OtaContext gains a folder_dest (registered by the app while a motatool `serve`
  link is up) + its human id (e.g. "tcp 192.168.4.5").
- `ota pull <#> <dest>` now takes a MANDATORY destination; `ota pull <#>` with none
  lists the choices (flash always; folder + its link id when connected).
- The ESP32 WiFi seeder registers/clears the folder destination on connect/close —
  the same connection both serves the folder and accepts pulls into it.

Captures an exact copy of a device's firmware over the mesh to build a delta
against. Pause/resume on a mid-pull disconnect follows.
2026-07-02 08:44:10 +02:00
Valentin Kivachuk Burda bd2ecb80a7 ota: seeder storage protocol (pull-to-folder) + motatool serve storage handlers
Add the device->host WRITE half of the mota-seeder link so a device can capture
a .mota it is fetching off-mesh into the host folder (the same --dir used for
serving), stored as <mid>.mota — e.g. to grab an exact copy of a device's
firmware to build a delta against firmware you don't otherwise have.

- MotaSeederProto: OP_STAT / OP_BEGIN / OP_WRITE / OP_SREAD / OP_FIN (keyed by
  mid). Resume needs no host bookkeeping: BEGIN 0xFF-fills the file; on reconnect
  the device SREADs the leaves and re-requests only missing blocks (same as flash
  resume). Partial = <midhex>.mota.part, published to <midhex>.mota on FIN.
- motatool `serve --dir <folder>` now also handles the storage ops on the same
  folder/connection (SeederCore gains the store dir; serve_loop frames the
  variable-length WRITE). Host round-trip test added.

Firmware side (FolderMotaStore + `ota pull <#> <dest>` + pause/resume) follows.
2026-07-02 08:32:00 +02:00
ripplebiz affe61dc3b Merge pull request #2880 from ckoehler/push-sonzsorqmwqz
refactor: split MeshTables::hasSeen into pure query + markSeen
2026-07-02 13:58:48 +10:00
Christoph Koehler 4f701b7aec refactor: split MeshTables::hasSeen into pure query + markSeen
hasSeen() was simultaneously a predicate and a mutator — it inserted the
packet hash on every miss, making five call sites that only wanted to mark
a packet as sent call it with the return value discarded.

Split into:
- wasSeen()   — pure predicate, no side effects
- markSeen()  — explicit insert

All query sites now call markSeen() immediately after wasSeen() returns
false, preserving identical runtime behaviour. The five mark-only send
sites (sendFlood, sendDirect, sendZeroHop x2) now call markSeen directly.

Also fixes three bridge sites (BridgeBase, ESPNowBridge, RS232Bridge)
that had the same query+implicit-insert pattern.

Tests: add test/test_mesh_tables/ covering wasSeen purity, markSeen,
dup stats, and clear. Update SHA256 mock to produce deterministic output
(previously finalize() was a no-op). Add Packet.cpp to native build filter.
2026-07-01 21:51:38 -06:00
Liam Cottle dd87371574 Merge pull request #2873 from ckoehler/fix/nix-devshell
build: add gcc, gtest to nix shell, fix native test framework
2026-07-02 11:32:21 +12:00
mikecarper dc4ac60efc Sort power variants before roles 2026-07-01 15:12:22 -07:00
mikecarper 6c27c00fbc Group radio variant device tiles 2026-07-01 09:55:35 -07:00
mikecarper 7e4c460603 Group Ikoka Handheld variants 2026-07-01 09:51:03 -07:00
Christoph Koehler 4f7c1cb88f build: add gcc, gtest to nix shell, fix native test framework 2026-07-01 08:19:27 -06:00
mikecarper 29842afcc0 Describe custom Mesh America roles 2026-07-01 00:04:12 -07:00
mikecarper 60a4dee3aa Map bridge builds to repeater role 2026-06-30 23:54:01 -07:00
mikecarper 04a90654ae Add pin notes for split Mesh America boards 2026-06-30 23:45:44 -07:00
mikecarper 33269aef53 Split unsafe Mesh America folds 2026-06-30 23:40:37 -07:00
mikecarper bd3decc864 Refine Mesh America catalog metadata 2026-06-30 23:34:38 -07:00
mikecarper 53a86491ac Keep distinct LilyGo hardware entries 2026-06-30 14:25:20 -07:00
mikecarper da7b90a1ac Fold additional Mesh America device names 2026-06-30 14:21:57 -07:00
mikecarper bcb75839dd Improve Mesh America device name matching 2026-06-30 14:18:23 -07:00
mikecarper 5ab52ca7c0 Add Mesh America provider catalogs 2026-06-30 14:12:34 -07:00
Valentin Kivachuk Burda 259802b706 ota: configurable hop limit (ota config hops) + accept-gate + forward RAM guard
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.
2026-06-30 20:35:48 +02:00
Valentin Kivachuk Burda 9ff1c883c2 ota: configurable advertise interval (default 24h) + advertise on served-set change
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`.
2026-06-30 14:29:38 +02:00
entr0p1 2cb3a29fa8 SX1262 LDO Support
- Added build flag "SX126X_USE_REGULATOR_LDO" (set to 1 to enable) to use LDO for the SX1262 radio instead of DC-DC when the DCDC pin isn't wired up (e.g. t-echo lite)
- Added additional debug mode diagnostic messages during SX1262 init to better highlight faults
2026-06-30 16:55:16 +10:00
mikecarper 28ee5d2c4b Add resume support for logging matrix builds logging-v1.16.0-halo-keymind-dev-28ee5d2c v1.16.0-halo-keymind-dev-28ee5d2c 2026-06-29 23:09:39 -07:00
mikecarper 37892bb905 Update build all target handling 2026-06-29 23:05:32 -07:00
mikecarper d686c25108 Use logging infix for build artifacts 2026-06-29 13:10:54 -07:00
mikecarper 88fec6e512 Use keymind retry timing for direct paths 2026-06-29 12:55:58 -07:00
Jody Bentley 5c534c4399 thinknode_m6: don't drive GPS REINIT pin (fixes GPS never detected)
The M6's L76K GPS streams NMEA at 9600 baud on its own, but the firmware
reported no GPS. Root cause: pin 29 (PIN_GPS_RESET / the module's REINIT
line) was driven HIGH, which holds the L76K silent so it never emits any
sentences and detection fails.

variant.cpp drove pin 29 HIGH at boot, and because PIN_GPS_RESET was
defined, MicroNMEALocationProvider also drove it HIGH in begin(). Bench
testing on a sealed M6 (passive NMEA capture, no logic analyzer) confirmed:
pin 29 driven HIGH = 0 bytes; pin 29 floating = full NMEA stream.

Define GPS_RESET (-1) so the location provider never touches pin 29, and
stop driving it in initVariant. This matches the Meshtastic M6 variant,
which leaves the same pin as a floating input.
2026-06-29 14:49:11 -04:00
Valentin Kivachuk Burda 0a1cf2b231 ota: enable OTA on the nRF52 variants the OTAFIX bootloader supports
Switch these existing variants from `nrf52_base` to `rak4631_hw` (which adds
ENABLE_OTA + the in-place flash store + the EndF post-build hook), so they get
OTA-over-LoRa. Scope is limited to variants already covered by the
Adafruit_nRF52_Bootloader_OTAFIX in-place apply — no new variants are added.
OtaTargets.h is regenerated to include their target ids.
2026-06-29 20:44:59 +02:00
Valentin Kivachuk Burda 4cb118b422 ota: faster post-boot beacon + periodic re-announce + clearer ota ls
Discovery was hard to use — a node only advertised at boot, so a peer that
ran `ota ls` minutes later saw "no neighbours".

- First self-advert ~8s after boot, then a short burst (~1 min), then
  re-announce at a random 3-10 min interval so a long-running node stays
  discoverable without all nodes beaconing in lockstep. The beacon is tiny,
  lowest-priority and duty-gated, so a few-minute cadence is cheap.
- `ota ls` now shows the raw target id (`hw XXXXXXXX`) when the env name is
  not in this build's OtaTargets.h table, instead of a blank "[other hw]".
2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 280b9b1555 ota: serve & manage OTA over WiFi (motatool --tcp + ESP32 companion seeder/console)
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).
2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 54c8b586c1 ota: protocol spec + user guide 2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda e3dd6b417f ota: native unit tests (format/merkle/detools/apply vectors) 2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 2092500d2b ota: motatool — portable C++ .mota packager + relay (build/verify/inspect/serve/keygen) 2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 4680d1052f ota: build/board enablement (platformio, build.sh, variants) + Python tooling (.mota reference, EndF/target/vector generators) 2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 543c90119e ota: CLI commands + node/CommonCLI integration + example hooks 2026-06-29 20:24:24 +02:00
Valentin Kivachuk Burda 9beaf6848e ota: relay an external folder of .mota over USB serial (MotaSource) 2026-06-29 20:17:07 +02:00
Valentin Kivachuk Burda 9b61169c16 ota: platform apply + flash staging (ESP32 A/B, nRF52 in-place via bootloader) 2026-06-29 20:17:07 +02:00
Valentin Kivachuk Burda 5da783040f ota: LoRa transfer protocol + session manager (discovery, block fetch/serve) 2026-06-29 20:17:07 +02:00