Commit Graph
1549 Commits
Author SHA1 Message Date
mikecarper bbb5c14fba Merge branch 'keymindCascade' of github.com:mikecarper/MeshCore into keymindCascade
# Conflicts:
#	test/test_nrf52_ble_startup.py
2026-09-24 17:36:09 -07:00
mikecarper a74a09da56 Complete ESP32 partition expander and adaptive LoRa OTA pacing 2026-09-24 17:13:22 -07:00
mikecarper e370db7f28 Safely hand off expanded ESP32 LoRa bridge without resume record 2026-09-24 12:17:49 -07:00
mikecarper 09d5bd9975 Add LoRa partition migration recipes for ESP32 infrastructure boards 2026-09-24 10:40:32 -07:00
mikecarper 9e48f516ba Expand ESP32 OTA partition migration across infrastructure roles 2026-09-24 10:01:14 -07:00
mikecarper cbfe5f79ea Merge observer firmware branch into keymindCascade
Integrate compatible observer board, preset, WebConfig, display, CI, and policy updates. Preserve the checkout's newer MQTT binary preferences and WiFi bridge runtime where the forked implementations conflict. Keep ThinkNode observer networking WiFi-based until the Ethernet transport is wired into that runtime.
2026-09-24 01:20:56 -07:00
mikecarper 78eb7d52c9 Merge upstream dev into keymindCascade 2026-09-24 00:51:07 -07:00
mikecarper 6976877f04 Select registered OTA slots and verify LoRa staging geometry 2026-09-23 23:33:29 -07:00
mikecarper f8a1e2ff96 Add in-place ESP32 Wi-Fi and LoRa partition migration packages 2026-09-23 22:12:45 -07:00
mikecarper 960936183c Refresh nRF52 Companion BLE name without reboot 2026-09-23 14:12:37 -07:00
mikecarper e6b002759d fix(build): clear matrix failures while preserving features 2026-09-22 23:23:25 -07:00
mikecarper 49ceda27ba Fix fallback RNG seed for recoverable Companions 2026-09-22 16:35:44 -07:00
mikecarper 80f37d4374 Harden nRF52 filesystem recovery and flash writes 2026-09-22 15:17:39 -07:00
mikecarper 3ce499a700 Fix nRF52 flash completion and preserve recoverable ExtraFS 2026-09-22 09:29:05 -07:00
mikecarper 6fb8e430ff fix(usb): preserve platform startup ordering 2026-09-22 07:49:40 -07:00
mikecarper 8ecdd31585 fix(t1000e): restore single-port usb logging 2026-09-22 07:46:11 -07:00
mikecarper 04e6aa38f2 fix(nrf52): stabilize full companion bluetooth 2026-09-22 05:54:46 -07:00
Scott Powell 560fb847d5 missing board.loop() in companion, room server, kiss modem. 2026-09-22 18:01:15 +10:00
mikecarper bea968b4fa feat(radio): calibrate dual-profile preambles from live switch timing 2026-09-22 00:09:37 -07:00
ripplebiz a76d511ff4 Merge pull request #3131 from liekmarflow/feature/board-api-hooks
Add board loop hook for periodic work
2026-09-22 16:43:18 +10:00
Wolfram Keil 61be70849a Add board loop hook for periodic work 2026-09-22 08:01:48 +02:00
mikecarper a95f7b3d16 feat(ui): page radio and system status 2026-09-21 15:35:46 -07:00
Blake Latchford 0c3fe356d0 Constrain agc.reset.interval and allow intervals > 255s 2026-09-21 12:26:36 -04:00
ripplebiz 65737d48f4 Merge pull request #3402 from meshcore-dev/sensor-improvements
Sensor improvements
2026-09-21 19:03:18 +10:00
mikecarper 01ad5ca8a8 feat(kiss): add dual-profile radio2 support for OpenHop 2026-09-20 07:59:43 -07:00
ripplebiz b37e7dd955 Merge pull request #3431 from meshcore-dev/abstract-ui-overhaul
Abstract UI overhaul
2026-09-20 18:08:29 +10:00
mikecarper 9844982b00 Add Wi-Fi OTA partition migration support 2026-09-19 20:14:37 -07:00
liamcottle 73afe3a0f5 allow fetching configured wifi password via companion cli 2026-09-20 14:22:13 +12:00
agessaman da6406e92f fix(network): rebuild the DHCP hostname when the node is renamed
The hostname was built once in begin() from the node name, so `set name` left
the node advertising its old name to DHCP until the next reflash. It is now
rebuilt on rename through a new CommonCLICallbacks::onNodeNameChanged() hook,
and begin() shares the same helper.

What this cannot do is rename a live lease. IDF 4.4 states that a hostname
changed after the interface is up "would only be reflected once the interface
restarts/reconnects", and Arduino 2.x's WiFi.setHostname() does not touch a
running netif at all — it writes a static string that the netif reads at
bring-up. Forcing the issue would mean bouncing the link, which costs every
MQTT slot a reconnect; that is not a reasonable price for a rename, so the new
name lands at the next reconnect or boot instead.

Only automatic (Ethernet-preferred) links carry a hostname today, exactly as
before. Giving plain Wi-Fi observers one would change the DHCP identity of the
existing fleet and is a separate decision.
2026-09-19 15:57:45 -07:00
agessaman 25f26c3058 Merge fix/mqtt-review-2026-09-09 into feat/abstract-networking
#54 lands first, so the network abstraction is reworked on top of the
per-slot client ownership model instead of alongside it.

Two resolutions are semantic, not textual:

- Link-transition teardown goes through the ownership API. It called
  softDisconnect() on every started client, which bypassed client_state and
  ignored the typed result. A slot that is still Starting now gets a real
  stop: softDisconnect() returns immediately on a client that is not yet
  connected, so its attempt would otherwise complete against the old route and
  deliver a CONNECTED event indistinguishable from the new one's (F04). On a
  medium switch the old route can still be briefly usable, so that is not
  hypothetical. A connected client keeps the cheap bounded path, and a
  quarantined one is left alone.

- NetworkLink::applyPowerPrefs() adopts WifiPowerSavePolicy. Its local
  `2 ? MAX : NONE` mapping would have reintroduced F11 and read the new stored
  value 3 (explicit `min`) as none. It also applies the setting when the link
  starts already associated, which is the case the bridge used to cover.

The NTP probe from #54 keeps its validation and its one-attempt-per-server
bound, but resolves and gates on the selected link rather than on WiFi, so it
works on an Ethernet-preferred node.
2026-09-19 15:15:07 -07:00
agessaman 16562621a2 fix(mqtt): gate room-server OTA on an unproven stop; reap late acks
- The room server checked canFlashAfterStop() only when the bridge was
  running at OTA time. After a timed-out restart the bridge reads as
  stopped while its unacknowledged task may still own TLS/client state,
  so an OTA could erase and write flash under it. It now refuses while
  the stop is unproven, after first reaping any late ack. The repeater
  already gated unconditionally.
- MyMesh::loop() now reaps a late stop acknowledgement whenever it lands,
  releasing the withheld queue and buffers, and restarts only when a
  resume is pending and the bridge is enabled. Before, a bridge disabled
  during StopUnproven kept those resources until re-enabled or rebooted.
  pollLateStopAck() is public for this.
- The wrapper's destructor no longer stops an already-stopped client:
  destroySlotClients() had just stopped it, so every shutdown logged five
  spurious "esp_mqtt_client_stop failed: ESP_FAIL" errors.

Hardware (Heltec V4, 1 s test stop deadline): restart -> StopUnproven ->
`set bridge.enabled off`; the late ack was reaped ("releasing withheld
resources"), status read "not running", and `set bridge.enabled on`
started cleanly without a second release.
2026-09-19 14:22:00 -07:00
agessaman d180f097ea fix(mqtt): an explicit bridge stop cancels a pending late-ack resume
setBridgeState(false) returned early when the bridge was already down,
so `set bridge.enabled off` after a timed-out restart left the resume
pending and MQTT restarted against the operator's choice once the task
acknowledged. Disabling now clears the pending resume before that early
return, and the resume also requires bridge_enabled. The StopUnproven
log and `get mqtt.status` no longer say only "reboot to recover", since
a late ack now recovers on its own.

Hardware (Heltec V4, 5 live slots, 1 s test stop deadline): a restart
went StopUnproven, the task acknowledged 27 s later and the bridge
resumed with all slots reconnecting; with `set bridge.enabled off` in
between it stayed stopped until `set bridge.enabled on`.
2026-09-19 13:58:49 -07:00
agessaman f50a6a3940 fix(mqtt): resume after a late stop ack; bound the hourly NTP refresh
- A stop that timed out into StopUnproven refused begin(), and only a
  later begin() honoured the task's late acknowledgement. Nothing called
  it, so restartBridge() (any `set mqtt...` restart) or an aborted OTA left
  the observer offline for the rest of the boot. MyMesh now records that a
  start was refused and restarts the bridge once stopAcknowledgedLate()
  reports the ack. The OTA-abort alert no longer claims "bridge resumed"
  when the restart was refused.
- refreshNTP() now runs the validated probe with one attempt per server.
  With two attempts and a 1 s pause it blocked the MQTT task ~18 s every
  hour on networks that drop UDP/123, where the old async SNTP cost
  nothing. Loop comment and docs updated to match.
2026-09-19 11:27:01 -07:00
agessaman 3c39908720 fix(webconfig): read the LAN address after pinning the route
startLanMode() took the caller's IP, read before the route lock. A
Wi-Fi/Ethernet switch in between left WebConfig locked to the new link
while advertising the old link's address. It now reads the selected
link's address after lockSwitching(), as startOTAUpdate() already does.
2026-09-19 10:53:39 -07:00
agessaman eb39ca59e7 fix(webconfig): persist the admin password before completing Ethernet onboarding
The upstream `password` command saves /prefs.json without reporting the
result, and WebConfig overwrites its reply with "OK". If that write failed
while the later /mqtt.json write succeeded, wifi.setup_complete was set and
the factory password came back after reboot with first-run setup
suppressed. onInitialSetupComplete() now re-saves /prefs.json and records
completion only when it succeeds; otherwise the batch fails, setup stays
open, and no reboot is queued.
2026-09-19 10:35:49 -07:00
agessaman 4c683b13b3 fix(network): pre-merge review fixes
- Guard the boot-time link bootstrap to observer ESP32 builds. It ran
  unconditionally in MyMesh::begin(), breaking every non-observer
  repeater/room server build (ESP32 and nRF52).
- Rename NetworkInterface -> NetworkLink (class, accessor, files).
  Arduino-ESP32 3.x ships its own NetworkInterface class and header,
  which broke the ESP32-C6 builds. Drop WiFi.setAutoConnect(), a no-op
  on 2.x and removed in 3.x.
- Refresh stored Wi-Fi credentials every bridge tick so the STA
  reconnect loop picks up `set wifi.ssid` / `set wifi.pwd` without a
  reboot, as the bridge did before the link moved out of it. Skip
  reconnects while the SSID is empty.
- Restore the "WiFi connected: <ip>" / "WiFi disconnected: reason N"
  debug lines the bridge used to print.
- Alert on Ethernet only once it has held a lease this boot or when no
  Wi-Fi is configured; Wi-Fi-only installs of an Ethernet-preferred
  image keep Wi-Fi alerts instead of reporting "Ethernet down".
- Record wifi.setup_complete only for Ethernet LAN onboarding, so
  Wi-Fi builds keep the SSID-based first-boot portal rule.
- Use seq_cst for the route-switch lock/mutation flag handshake.
- Docs: SNMP RSSI sentinel is -127; describe link-return vs medium-switch
  reconnect behavior accurately; note runtime credential pickup.
- Test: unknown keys inside a known /mqtt.json group are ignored, which
  keeps wifi.setup_complete downgrade-safe.
2026-09-19 10:14:16 -07:00
agessaman ad65f64156 Merge branch 'observer-firmware-dev' into feat/abstract-networking 2026-09-19 09:23:32 -07:00
Scott Powell 64434c5326 * misc 2026-09-19 20:13:18 +10:00
Kevin Le c425648bfc Off LED before powering off for repeater 2026-09-19 11:26:42 +07:00
mikecarper 9d91b039bf Fit Wio companion USB logging 2026-09-18 11:24:18 -07:00
Scott Powell 843598724c * fix for X1 2026-09-18 19:03:20 +10:00
mikecarper e708d0d14e Fix capacity matrix build regressions 2026-09-17 23:54:11 -07:00
Liam Cottle 166f75c1b6 Merge pull request #3442 from liamcottle/feature/companion-cli-commands
added reboot, shutdown and poweroff to companion cli commands
2026-09-18 18:25:33 +12:00
liamcottle 242e401a2c added reboot, shutdown and poweroff to companion cli commands 2026-09-18 18:17:52 +12:00
agessaman d42c4249a5 Merge upstream/dev into observer-firmware-dev 2026-09-17 21:19:23 -07:00
Blake Latchford 1077331e31 Extend WiFi disconnect logging to specify reason
Today if a user builds firmware with an incorrect WiFi SSID or password,
they get a generic `WiFi disconnected.` error message.

Extend logging to descirbe the reason that WiFi was disconnected.

I gathered the updated logs for the 3 scenarios below.

```
WiFi: Attempting manual WiFi reconnect...
WiFi: WiFi disconnected (reason=ASSOC_LEAVE). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
WiFi: WiFi disconnected (reason=4WAY_HANDSHAKE_TIMEOUT). Flagging for reconnect...
```

```
WiFi: WiFi disconnected (reason=NO_AP_FOUND). Flagging for reconnect...
```

```
WiFi: WiFi connected successfully!
WiFi: Got connection
```
2026-09-17 19:39:51 -04:00
mikecarper ee3390d628 Merge IoTThinks PowerSaving-v17 changes
# Conflicts:
#	examples/companion_radio/main.cpp
#	src/helpers/TxtDataHelpers.cpp
2026-09-17 14:39:06 -07:00
mikecarper ab18216718 Consolidate companion components 2026-09-17 13:41:39 -07:00
mikecarper 30067cb5cd Split MQTT and ESP-NOW controls in Full ESP32 builds 2026-09-17 01:13:10 -07:00
mikecarper 9a149eaea1 Combine ESP-NOW and MQTT in ESP32 Full builds 2026-09-17 00:37:32 -07:00