With saved credentials present (seeded from the WIFI_SSID build flag on
first boot), the recovery AP came up in AP+STA mode while auto-reconnect
and the 10s manual retry kept the station scanning. STA scans drag the
shared radio across channels, so joining clients' WPA2 handshakes timed
out - reported by phones as a wrong password.
Disable auto-reconnect and pause the 10s retry loop while the recovery
AP is active; retry the configured network once a minute instead, so the
AP stays stable between attempts and the node still self-recovers (and
shuts the AP down) when its network returns.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a companion WiFi device has no WiFi credentials or can't connect for
60s, it broadcasts an 'EastMesh-WiFi' AP (WPA2 password = device pin
zero-padded to 8 digits; open if no pin set) with the rescue CLI on TCP
port 23, so wifi.ssid/pwd can be fixed without a serial cable.
- rescue CLI command handler now writes to any Stream (Serial or the TCP
rescue client)
- while the AP is up, STA keeps retrying; the AP shuts down automatically
once the configured network connects
- 'set wifi.ssid/pwd' keeps AP+STA mode during a rescue session so the
session isn't dropped mid-config
- guard ESP32-only SD/SPI code in ArchiveStorage so non-ESP32 builds of
the shared helpers get further
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Integrates upstream v1.17.0. Key adaptations:
- companion + repeater NodePrefs moved to upstream's new ConfigSerializer
(prefs.json) format; EastMesh fields (companion wifi, repeater fan and
MQTT bridge peer) appended as serializer groups/keys
- legacy binary prefs loaders retain EastMesh tail fields, so existing
devices migrate their settings to the new format
- companion main.cpp adopts upstream InterfaceManager while keeping
runtime WiFi credentials from prefs
- kept EastMesh release-tag versioning in setup-build-environment action
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The companion_radio example was not restoring the GPS enabled/disabled
preference from flash after reboot. The preference was being saved
correctly when toggled via the mobile app, but on boot,
sensors.begin() -> initBasicGPS() unconditionally sets gps_active=false
and nothing subsequently restored the persisted state.
Added applyGpsPrefs() (matching the pattern in simple_repeater,
simple_sensor, and simple_room_server) and call it from main.cpp
after sensors.begin() to ensure the GPS hardware is initialized
before the saved preference is applied.
Filter auto-add of new contacts by hop count (issues #1533, #1546).
Setting is configurable from the companion app via extended
CMD_SET/GET_AUTOADD_CONFIG protocol (0 = no limit, 1-63 = max hops).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>