With --reboot, a restore of the radio alone brings it back as it was:
on a board without Ethernet it read the radio from the wrong place.
--firmware <firmware.bin> updates the device through /updateFirmware and
checks it still runs a minute later, after it marks the update good.
wait_for_restart compared uptimes, so a test run right after another
restart could see more uptime than before and fail. It compares boot
times, and waits while the device hasn't restarted yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The web UI sends the restore options as the form field "data". The
param helpers looked up query parameters only, so /restore never saw
them and restored the shades alone, since 3.0.0. The helpers now take a
form field too.
/restore uses an upload once, and drops the file when the options aren't
JSON.
e2e: test_restore.py, a probe that the field is read and, with --reboot,
a settings-only round trip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- shadeRemoved, groupRemoved and roomRemoved went out from the deletes,
before the edit's reply. They now come from editChanges and go out with
the edit's other events, after it (test_adding_and_deleting_a_room).
- test_reboot reconnected in the moment between the sockets closing and the
restart, and waited for a hello that never came. It now waits, retries a
connect without hello, and checks the uptime went back.
e2e on the device (esp32s3dbg): 72 passed, 3 skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The frequency scan ops and reboot run on loop() like every op (ADR 0005).
endFrequencyScan goes to the front of the loop queue, so it never waits
behind an unpair that waits for the scan to end.
- A security save that leaves the device Secured, or changes its mode,
closes every client, the saver too once its reply has gone. None to None
closes nobody.
- proto must be a radio_proto value; frequency, rxBandwidth and deviation
are checked against what the CC1101 can be set to.
- wifiNetworks sends fewer networks instead of none when they don't fit.
- A client WiFi scan doesn't start while the device joins a network.
- rebootTime is set before reboot; cancelSettingsSave is freeSettingsSave.
- PROTOCOL.md: pins that may be -1, and the fields the routes sent that
moved elsewhere. e2e: the WiFi scan test goes by the connection in use.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step 1d of the protocol 2 core (docs/SECURITY_PLAN.md).
- getSettings/saveSettings by section: general, network, mqtt, security,
radio. A save is the settings route's request, so loop() applies it with
the settings' own fromJSON(). ProtoSettings checks every field first:
kind, range, string length, IP addresses.
- Secrets are only reported as has*. A security save replies with the
client's new token and closes the other sockets; other saves send
settingsChanged to the other clients.
- scanWifi runs an async scan from ESPNetwork, kept apart from the roaming
scan, and wifiNetworks goes to the clients that asked.
- beginFrequencyScan, endFrequencyScan and reboot run at once on async_tcp,
as their routes do: a scan's end mustn't wait in the loop queue behind an
unpair that waits for the scan to end (new op kind 'a').
- e2e: test_settings.py and a --reboot flag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>