You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+5-7Lines changed: 5 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,32 +14,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
14
15
15
### Added
16
16
17
-
-**OTA MVP** — three new crates for end-to-end firmware update on ESP32-C3 (and ESP32-C6 / ESP32 for the bare-metal stack), aligned with `docs/adr/011-ota-crate-hosting-and-transport.md` and `docs/features/ota-mvp-v1.md`. All public APIs are explicitly experimental for MVP; stabilization is owned by the future `ota-library` feature.
17
+
-**OTA MVP** — three new crates for end-to-end firmware update on ESP32-C3 (and ESP32-C6 / ESP32 for the bare-metal stack), aligned with `docs/adr/011-ota-crate-hosting-and-transport.md` and `docs/features/archive/ota-mvp-v1.md`. All public APIs are explicitly experimental for MVP; stabilization is owned by the future `ota-library` feature.
18
18
-`ota-pure` (new crate, **experimental API**) — platform-independent, `no_std`, host-tested. Surface: `Version` semver parser (`u16` components, `Display`, `Ord`), `StreamingVerifier` (chunk-fed SHA-256 over `sha2 = { default-features = false }`), `bytes_to_hex` / `hex_to_bytes` fixed-size helpers (returns `heapless::String<64>`), `ImageMetadata` sidecar parser (`.bin.sha256` + `.bin.version`), backend-neutral `OtaState` enum (`Idle → Downloading → Verifying → Writing → SwapPending → Booted`) with `next_state()`, and `OtaError` with the 8 MVP variants (`ServerUnreachable`, `DownloadFailed { status: u16 }`, `DownloadTimeout`, `ChecksumMismatch`, `VersionInvalid`, `FlashWriteFailed`, `PartitionNotFound`, `InsufficientSpace`). `DownloadFailed { status: 0 }` is reserved as a sentinel for protocol-shape rejections from the bare-metal HTTP client. 37 host unit tests.
19
19
-`rustyfarian-esp-idf-ota` (new crate, **experimental API**, blocking) — ESP-IDF std, lifted from `rustyfarian-beekeeper/src/ota/`. Surface: `OtaSession::new(config)`, `fetch_and_apply(url, &expected_sha256)`, `mark_valid()`, `rollback()`. Wraps `EspOta` / `EspOtaUpdate` and `EspHttpConnection`; streams download → SHA-256 verify (`StreamingVerifier`) → flash → swap in one pass without holding the full image in RAM. Strips RFC 3986 userinfo from URLs before logging (no credential leakage to `espflash monitor`). HTTPS rejected at MVP scope per ADR 011 (`ota-hardened` will revisit).
20
20
-`rustyfarian-esp-hal-ota` (new crate, **experimental API**, async-only) — bare-metal `no_std`, built fresh against `esp_bootloader_esp_idf::OtaUpdater` over `esp-storage` and `embassy-net::TcpSocket`. Surface: `EspHalOtaManager::new(config, FLASH<'d>)`, `async fetch_and_apply(socket, url, &expected_sha256)`, `mark_valid()`, `rollback()`. Carries an internal hand-rolled HTTP/1.1 GET parser (per ADR 011 §2): accepts only `HTTP/1.1 200 OK` with exactly one valid `Content-Length`; rejects redirects, `Transfer-Encoding: chunked`/`identity`, missing or duplicate `Content-Length`, non-`1*DIGIT` numeric values (incl. leading `+`/`-`), whitespace before colon, oversized bodies, and short reads. Chip features `esp32c3` (MVP), `esp32c6`, `esp32`; stack features `unstable`, `rt`, `embassy`. Host stub mirrors the wifi-crate pattern (typecheck-only). 29 parser unit tests.
21
21
- Workspace: `sha2 = { version = "0.10", default-features = false }`, `esp-storage = "=0.9.0"`, `embedded-storage = "0.3"` added to `[workspace.dependencies]`; `embedded-svc = "0.29"` declared (aligning with `esp-idf-svc 0.52`).
- CI (`.github/workflows/rust.yml`): host tests for `ota-pure` and `rustyfarian-esp-hal-ota --no-default-features` added to the "Test pure crates" block.
24
24
- Build scripts: `scripts/detect-port.sh` narrows `espflash`'s auto-detect to USB serial devices (`usbmodem*`/`usbserial*` on macOS, `ttyUSB*`/`ttyACM*` on Linux) so paired Bluetooth ports stop hijacking the probe; used by `flash.sh`, `just run`, `just monitor`, and `just erase-flash`. `ESPFLASH_PORT=…` still wins when set explicitly
25
-
-`rustyfarian-esp-hal-wifi`: `embassy` Cargo feature + `WiFiManager::init_async()` returning an `AsyncWifiHandle { controller, stack, runner }` wired into an `embassy-net` stack with automatic DHCPv4 (`AsyncWifiHandle::wait_for_ip().await` awaits the first lease). Originally landed alongside a synchronous `WiFiManager::init` path that drove `smoltcp` directly; that sync path was removed later in this same release cycle when the stack moved to `esp-radio 0.18` (see the breaking-change entry below). The `embassy` feature is now the only supported Wi-Fi path on bare-metal — see `docs/features/embassy-feature-flag-v1.md` and `docs/features/wifi-manager-async-v1.md`
25
+
-`rustyfarian-esp-hal-wifi`: `embassy` Cargo feature + `WiFiManager::init_async()` returning an `AsyncWifiHandle { controller, stack, runner }` wired into an `embassy-net` stack with automatic DHCPv4 (`AsyncWifiHandle::wait_for_ip().await` awaits the first lease). Originally landed alongside a synchronous `WiFiManager::init` path that drove `smoltcp` directly; that sync path was removed later in this same release cycle when the stack moved to `esp-radio 0.18` (see the breaking-change entry below). The `embassy` feature is now the only supported Wi-Fi path on bare-metal — see `docs/features/archive/embassy-feature-flag-v1.md` and `docs/features/archive/wifi-manager-async-v1.md`
26
26
-`rustyfarian-esp-hal-wifi`: `hal_c3_connect_async` example — first async bare-metal Wi-Fi demo on ESP32-C3, uses `#[esp_rtos::main]` with two spawned tasks (`wifi_task` for association + reconnection, `net_task` for the embassy-net runner), prints the DHCP-assigned IP and idles asynchronously (see `docs/features/hal-c3-connect-async-example-v1.md`)
27
27
- Build scripts: `scripts/build-example.sh` now appends the `embassy` feature automatically for any `hal_*_async*` example
28
28
- Justfile: `check-wifi-hal-embassy` recipe that verifies the `embassy` feature compiles for ESP32-C6 (`riscv32imac-unknown-none-elf`) and ESP32-C3 (`riscv32imc-unknown-none-elf`)
29
29
-`espnow-pure`: `PeerTracker` — heartbeat-based peer liveness tracker with online/offline transition detection, extracted from rustbox-rgb-puzzle brain firmware
30
30
-`espnow-pure`: `ScanConfig::with_probe_timeout()` and `DEFAULT_PROBE_TIMEOUT` (100 ms) — per-channel probe timeout is now configurable
31
31
-`espnow-pure`: `ScanConfig::with_burst_timeout()` and `DEFAULT_BURST_TIMEOUT` (3 s) — bounds total time the radio spends at boosted TX power during peer discovery
32
-
-`wifi-pure`: `TxPowerLevel` enum (`Lowest`, `Low`, `Medium`, `High`, `Max`) with `to_quarter_dbm()` mapping to ESP-IDF quarter-dBm values; `WiFiConfig::with_tx_power()` builder method (see `docs/features/wifi-radio-power-config-v1.md`)
32
+
-`wifi-pure`: `TxPowerLevel` enum (`Lowest`, `Low`, `Medium`, `High`, `Max`) with `to_quarter_dbm()` mapping to ESP-IDF quarter-dBm values; `WiFiConfig::with_tx_power()` builder method (see `docs/features/archive/wifi-radio-power-config-v1.md`)
33
33
-`rustyfarian-esp-idf-wifi`: applies `TxPowerLevel` via `esp_wifi_set_max_tx_power()` after Wi-Fi start
34
34
-`rustyfarian-esp-hal-wifi`: stores `TxPowerLevel` config; logs a warning that `esp-radio` does not expose a TX power API on bare-metal targets (true on both 0.17 and 0.18 — the radio default applies)
35
35
-`rustyfarian-esp-idf-espnow`: `scan_for_peer()` auto-bursts TX power to maximum during channel scanning, restores previous level after scan completes
36
-
-`espnow-pure`: `command` module — `CommandFrame<'a>` zero-copy parser, `SystemCommand` enum (`Ping`, `SelfTest`, `Identify`), tag range helpers, and response payload builders for the ESP-NOW Peripheral Command Framework (see `docs/features/espnow-peripheral-command-framework-v1.md`)
36
+
-`espnow-pure`: `command` module — `CommandFrame<'a>` zero-copy parser, `SystemCommand` enum (`Ping`, `SelfTest`, `Identify`), tag range helpers, and response payload builders for the ESP-NOW Peripheral Command Framework (see `docs/features/archive/espnow-peripheral-command-framework-v1.md`)
37
37
-`rustyfarian-esp-hal-wifi`: `ActiveLowLed<P>` adapter — implements `StatusLed` with inverted polarity for onboard LEDs wired active-low (e.g. ESP32-C3 Super Mini GPIO8)
38
38
-`rustyfarian-esp-hal-wifi`: `hal_c3_connect_async_led` example — async Wi-Fi connect with spawned `led_task` that blinks the onboard GPIO8 LED during connection, holds steady once IP acquired; uses `AtomicBool` for task coordination
39
39
-`rustyfarian-esp-hal-wifi`: `hal_c6_connect_async_led` example — async Wi-Fi connect with spawned `led_task` that pulses the onboard WS2812 RGB LED (GPIO8) blue via `PulseEffect` during connection, holds dim green once connected
40
40
- Build scripts: `build-example.sh` and `flash.sh` auto-detect `rustyfarian-esp-hal-ws2812` feature for `hal_c6_*_led*` examples
41
-
- Justfile: `check-wifi-hal-embassy` recipe that verifies the `embassy` feature compiles for ESP32-C6 (`riscv32imac-unknown-none-elf`) and ESP32-C3 (`riscv32imc-unknown-none-elf`)
42
-
-`espnow-pure`: `PeerTracker` — heartbeat-based peer liveness tracker with online/offline transition detection, extracted from rustbox-rgb-puzzle brain firmware
43
41
-`rustyfarian-esp-hal-wifi`: `EspHalWifiManager` with real `WifiDriver` implementation using `esp-radio 0.17.0` for bare-metal ESP32-C3/C6 (ADR 006 Phase 5); `hal_c3_connect` and `hal_c6_connect` examples
44
42
-`rustyfarian-network-pure`: `status_colors` module with shared LED colour palette (`BOOT`, `WIFI_CONNECTING`, `MQTT_CONNECTING`, `CONNECTED`, `ERROR`, `OFFLINE`)
45
43
-`rustyfarian-esp-idf-mqtt`: `MqttBuilder::build_and_wait()` with `StatusLed` support for visual boot feedback (cyan pulse while connecting, green on success, red on timeout)
@@ -61,7 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
61
59
62
60
### Changed
63
61
64
-
-**April 2026 esp-hal stack wave** — coordinated workspace-wide bump of every bare-metal crate to exact pins (`Cargo.toml``[workspace.dependencies]`): `esp-hal 1.0.0`→`=1.1.0`, `esp-rtos 0.2.0`→`=0.3.0`, `esp-radio 0.17.0`→`=0.18.0`, `esp-bootloader-esp-idf 0.4.0`→`=0.5.0`, `esp-alloc 0.9.0`→`=0.10.0`, `esp-println 0.16.1`→`=0.17.0`, `esp-backtrace 0.18.1`→`=0.19.0`; embassy ecosystem `embassy-executor 0.9`→`=0.10.0`, `embassy-net 0.7`→`=0.8.0`, `embassy-time 0.5`→`=0.5.1`, `embassy-sync` newly pinned at `=0.8.0`. `smoltcp` is now exact-pinned at `=0.12.0` but is no longer a direct dependency of `rustyfarian-esp-hal-wifi` — `esp-radio 0.18` removed the `smoltcp` feature in favour of `embassy-net-driver`. Coordinated with `rustyfarian-ws2812`'s April 2026 wave (see `docs/features/esp-hal-stack-upgrade-april-2026-v1.md`)
62
+
-**April 2026 esp-hal stack wave** — coordinated workspace-wide bump of every bare-metal crate to exact pins (`Cargo.toml``[workspace.dependencies]`): `esp-hal 1.0.0`→`=1.1.0`, `esp-rtos 0.2.0`→`=0.3.0`, `esp-radio 0.17.0`→`=0.18.0`, `esp-bootloader-esp-idf 0.4.0`→`=0.5.0`, `esp-alloc 0.9.0`→`=0.10.0`, `esp-println 0.16.1`→`=0.17.0`, `esp-backtrace 0.18.1`→`=0.19.0`; embassy ecosystem `embassy-executor 0.9`→`=0.10.0`, `embassy-net 0.7`→`=0.8.0`, `embassy-time 0.5`→`=0.5.1`, `embassy-sync` newly pinned at `=0.8.0`. `smoltcp` is now exact-pinned at `=0.12.0` but is no longer a direct dependency of `rustyfarian-esp-hal-wifi` — `esp-radio 0.18` removed the `smoltcp` feature in favour of `embassy-net-driver`. Coordinated with `rustyfarian-ws2812`'s April 2026 wave (see `docs/features/archive/esp-hal-stack-upgrade-april-2026-v1.md`)
65
63
- ws2812 cross-repo dependencies (`led-effects`, `rustyfarian-esp-idf-ws2812`, `rustyfarian-esp-hal-ws2812`) re-pinned from `tag = "v0.4.0"` to `tag = "v0.5.0"` — v0.5.0 is the April 2026 wave release that ships the matching exact pins for `esp-hal`/`esp-rtos`/`esp-radio`, so the resolved feature graph stays unified with this workspace's bare-metal stack
66
64
-**BREAKING**`rustyfarian-esp-hal-wifi`: API renames flowing through from `esp-radio 0.18` — `WifiDevice` → `Interface`, `ModeConfig::Client(ClientConfig)` → `Config::Station(StationConfig)`, `Interfaces.sta` → `.station`, `WifiEvent::StaDisconnected` → `StationDisconnected`, `WifiError::Disconnected` is now a tuple variant carrying `DisconnectedStationInfo`, `controller.is_connected()` returns `bool` directly (not `Result`), `controller.connect()`/`disconnect()` are async-only (`connect_async`/`disconnect_async`), `controller.wait_for_event(StaDisconnected)` becomes `wait_for_disconnect_async`, `esp_radio::wifi::new()` is now `(WIFI, ControllerConfig)` (the radio init parameter is gone — radio init is implicit)
67
65
-**BREAKING**`rustyfarian-esp-hal-wifi`: `set_config` is now idempotent in `esp-radio 0.18` and implicitly starts the controller and initiates association — the explicit `start()`/`connect()` calls that existed in 0.17 are no longer needed (or available)
Copy file name to clipboardExpand all lines: docs/ROADMAP.md
+7-10Lines changed: 7 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,12 @@
1
1
# Roadmap
2
2
3
-
*Last updated: April 2026*
3
+
*Last updated: May 2026*
4
4
5
5
The bare-metal stack is now aligned on the April 2026 esp-hal wave (`esp-hal 1.1.0` / `esp-radio 0.18.0` / `esp-rtos 0.3.0` / embassy 0.10), hardware-validated on ESP32-C3 and ESP32-C6.
6
6
The bare-metal Wi-Fi surface is now async-only — `esp-radio 0.18` removed direct `smoltcp` integration and made the controller async-only, so `WiFiManager::init_async` + `AsyncWifiHandle` is the single public path.
7
+
The OTA MVP three-crate triad (`ota-pure`, `rustyfarian-esp-idf-ota`, `rustyfarian-esp-hal-ota`) has landed on `main` per [ADR 011](adr/011-ota-crate-hosting-and-transport.md) and [`docs/features/archive/ota-mvp-v1.md`](features/archive/ota-mvp-v1.md); all public APIs are explicitly marked experimental and remain unreleased until v0.2.0.
7
8
TTN v3 LoRa validation remains blocked on hardware.
8
-
Next milestone: release v0.2.0 with the accumulated post-0.1.0 features (including this upgrade), then deliver the OTA MVP three-crate triad — design locked by [ADR 011](adr/011-ota-crate-hosting-and-transport.md) and [`docs/features/ota-mvp-v1.md`](features/ota-mvp-v1.md), unblocked by the April 2026 stack landing.
9
+
Next milestone: cut v0.2.0 bundling the accumulated post-0.1.0 features (April 2026 stack upgrade, async Wi-Fi, OTA MVP, command framework, power-save, ESP-NOW channel scanning).
9
10
10
11
```mermaid
11
12
%%{init: {
@@ -25,12 +26,7 @@ Next milestone: release v0.2.0 with the accumulated post-0.1.0 features (includi
25
26
timeline
26
27
title rustyfarian-network Roadmap
27
28
28
-
Ready : Wi-Fi Radio Power Config v1 — TX power levels, power-save enum, auto-burst during discovery (feature-doc)
29
-
30
-
Near term : Release v0.2.0 — EspHalWifiManager, async Wi-Fi on the April 2026 esp-hal wave, status_colors, non-blocking publish, power save, ESP-NOW channel scanning, command framework
: OTA MVP Stage 2 — rustyfarian-esp-idf-ota (OtaSession::fetch_and_apply / mark_valid / rollback) on ESP32-C3 via EspOta + EspHttpConnection
33
-
: OTA MVP Stage 3 — rustyfarian-esp-hal-ota async over embassy-net + esp_bootloader_esp_idf::OtaUpdater with strict internal HTTP/1.1 GET (ADR 011)
29
+
Near term : Release v0.2.0 — EspHalWifiManager, async Wi-Fi on the April 2026 esp-hal wave, OTA MVP triad, status_colors, non-blocking publish, power save, ESP-NOW channel scanning, command framework
34
30
35
31
Mid term : Phase 5 — TTN v3 EU868 OTAA validation (blocked on hardware)
- WiFiManager LED integration for esp-hal — `ActiveLowLed<P>` adapter, `hal_c3_connect_async_led` and `hal_c6_connect_async_led` examples (StatusLed support matching ESP-IDF; the synchronous `init_with_led` was later removed when the stack moved to esp-radio 0.18 — LED feedback now wires via spawned tasks alongside `init_async`)
67
-
- esp-hal Stack Upgrade — April 2026 wave: workspace exact-pinned to `esp-hal 1.1.0`, `esp-rtos 0.3.0`, `esp-radio 0.18.0`, `esp-bootloader-esp-idf 0.5.0`, `esp-alloc 0.10.0`, `esp-println 0.17.0`, `esp-backtrace 0.19.0`, `embassy-executor 0.10.0`, `embassy-net 0.8.0`, `embassy-time 0.5.1`, `embassy-sync 0.8.0`, `smoltcp 0.12.0`. `rustyfarian-esp-hal-wifi` collapsed to async-only (`WiFiManager::init_async` + `AsyncWifiHandle`) — sync surface and direct `smoltcp` integration removed (BREAKING for the bare-metal Wi-Fi consumers; `embassy` feature is now effectively required). Hardware-validated on ESP32-C3-DevKitM-1 and ESP32-C6-DevKitC-1; LoRa example builds clean for ESP32-S3 (Phase 5 hardware run separate). Tooling: `scripts/detect-port.sh` filters espflash's auto-detect to USB serial devices on macOS. See `docs/features/esp-hal-stack-upgrade-april-2026-v1.md`.
63
+
- esp-hal Stack Upgrade — April 2026 wave: workspace exact-pinned to `esp-hal 1.1.0`, `esp-rtos 0.3.0`, `esp-radio 0.18.0`, `esp-bootloader-esp-idf 0.5.0`, `esp-alloc 0.10.0`, `esp-println 0.17.0`, `esp-backtrace 0.19.0`, `embassy-executor 0.10.0`, `embassy-net 0.8.0`, `embassy-time 0.5.1`, `embassy-sync 0.8.0`, `smoltcp 0.12.0`. `rustyfarian-esp-hal-wifi` collapsed to async-only (`WiFiManager::init_async` + `AsyncWifiHandle`) — sync surface and direct `smoltcp` integration removed (BREAKING for the bare-metal Wi-Fi consumers; `embassy` feature is now effectively required). Hardware-validated on ESP32-C3-DevKitM-1 and ESP32-C6-DevKitC-1; LoRa example builds clean for ESP32-S3 (Phase 5 hardware run separate). Tooling: `scripts/detect-port.sh` filters espflash's auto-detect to USB serial devices on macOS. See `docs/features/archive/esp-hal-stack-upgrade-april-2026-v1.md`.
64
+
- OTA MVP — three-crate dual-stack firmware update: `ota-pure` (no_std, host-tested), `rustyfarian-esp-idf-ota` (blocking, ESP-IDF), `rustyfarian-esp-hal-ota` (async, bare-metal via `embassy-net` + `esp_bootloader_esp_idf::OtaUpdater`). Streaming SHA-256 verify, partition swap, rollback; strict internal HTTP/1.1 GET parser. All public APIs explicitly experimental (locked by [ADR 011](adr/011-ota-crate-hosting-and-transport.md) and [`docs/features/archive/ota-mvp-v1.md`](features/archive/ota-mvp-v1.md)).
68
65
69
66
</details>
70
67
@@ -87,7 +84,7 @@ timeline
87
84
88
85
### OTA MVP — Three-Crate Dual-Stack Firmware Update
89
86
90
-
Locked by [ADR 011](adr/011-ota-crate-hosting-and-transport.md) and detailed in [`docs/features/ota-mvp-v1.md`](features/ota-mvp-v1.md).
87
+
Locked by [ADR 011](adr/011-ota-crate-hosting-and-transport.md) and detailed in [`docs/features/archive/ota-mvp-v1.md`](features/archive/ota-mvp-v1.md).
91
88
Requested by `rustyfarian-ferriswheel-demo` (sibling repo).
92
89
All public APIs are explicitly marked experimental for the MVP; stabilization is owned by the future `ota-library` feature.
0 commit comments