Skip to content

v0.3 [beta]

Pre-release
Pre-release

Choose a tag to compare

@Ruhanpaco Ruhanpaco released this 15 Aug 17:22
· 41 commits to main since this release

This release makes the reader discoverable by phone ecosystems the standard
way, by merging a Matter Door Lock endpoint into the same firmware that
already carried the web UI, the setup portal and OTA — rather than shipping a
second, separate image. It also lands the first real NFC frontend.

Flashed and booted on an ESP32-WROOM-32 with 4 MB flash. Read Known
limitations
before expecting a phone to open anything.

New Features

  • Matter Door Lock endpoint: the reader now presents as Door Lock cluster 0x0101 with the Aliro provisioning feature, which is the only place SetAliroReaderConfig and the Aliro credential types exist (db13116)

    • SetAliroReaderConfig persists the reader key pair a controller sends and restarts the reader on it, so a commissioned device survives a power cut with the identity the controller believes it has
    • SetCredential with an Aliro endpoint key enrols a phone as an ordinary credential in access_control; the user and credential database persists to NVS and re-enrols everything it holds at boot
    • The commissioning payload, manual pairing code and a QR link are printed at boot and shown on the dashboard
    • New Matter card on the dashboard, plus POST /api/matter/pair to reopen commissioning for five minutes
    • Compiled out entirely without CONFIG_ALIRO_MATTER_ENABLE; the default build is unchanged and does not carry Matter
    • A tap is unchanged — NFC start to finish, working with the network down and no controller present
  • PN532 NFC driver: the first real frontend, SPI or I2C, split into a pn532 component with no dependency on the rest of the project (391e638, 6820af0)

    • Also provides the five symbols Espressif's m5nfc component does, so an esp-matter door lock can drive a PN532 where it expects an ST25R3916 (f0e54e3)
  • OTA image validation in the firmware: an upload whose header is not an app image is refused before a byte is written, naming the file to use instead (e654865)

    • The page already greyed out .factory. by filename, but that is JavaScript checking a name — useless against a renamed file or curl
    • The chip ID is checked too, so an esp32s3 build sent to an esp32 says so
  • Web interface authentication: a username and password, off by default, enforced on every endpoint that reads configuration or changes state -- including POST /api/ota, which until now would accept firmware from anyone who could reach the address

    • HTTP Basic, so the browser owns the prompt: no JavaScript, and it works inside a captive-portal window where a login page and a cookie do not
    • The expected header is built from the stored credentials and compared in constant time; nothing decodes attacker-supplied base64 into a buffer
    • A Security section on the Misc page, which states plainly whenever the login is off that /api/unlock and /api/ota are open to anyone
    • Replaces a session table that no handler ever called, whose tokens were index * 12345 + uptime

Fixes and Improvements

  • Wi-Fi station ownership: chip's ConnectivityManager was driving the station on its own schedule with no credentials -- they arrive through the setup portal and live in our configuration, not chip's -- and its connect attempt was in flight when net_manager called esp_wifi_set_config. The credentials the user typed were never applied, and the reader sat in a reconnect loop against a network it had been told about. The station is now ApplicationControlled, chip's own term for it

  • Setup mode runs the portal and nothing else. With no credentials there is not enough memory for the Matter stack alongside a SoftAP, its DHCP server and a captive DNS responder, and the symptom was httpd_start failed: ESP_ERR_HTTPD_TASK -- an access point serving nothing at all. Matter starts on the next boot, once there is a network to be discovered on

  • Credential key slots: PSA is now initialised before the first derivation. Deriving on a cold PSA failed with a bare ESP_FAIL that reads exactly like a malformed key, which cost two hardware debugging sessions before the library was disassembled (957285f)

  • Credential store: keys are copied rather than referenced, re-adding a key replaces it instead of consuming a second slot, and credentials can be withdrawn. A credential arriving over Matter lives on the caller's stack and is gone when the command returns (7f4cac3)

  • Key slot re-derivation: a slot is a function of the credential key and the reader's group sub-identifier, so adopting a new reader identity invalidates every slot derived under the old one — the failure mode being a reader that answers every tap with "unknown credential" and never says why

  • Wi-Fi: backs off between reconnects, and offers a way back from the setup portal (c2f0694)

  • Wi-Fi ownership: net_manager reuses an existing netif and driver instead of creating a second default netif (which aborts) and calling esp_wifi_init on a running driver (which does not). Confirmed on hardware in the Matter build

  • Serial console: now a Kconfig option, off for the Matter build. Starting the REPL moves stdout onto the driver-based UART VFS, and with chip, NimBLE and Wi-Fi logging concurrently that asserted inside a blocking semaphore take, then recursed through the panic handler's own logging until the stack was gone (2ed1a6d)

  • Configuration UI vs. lwIP sockets: the web server failed to start with ENOBUFS in the Matter build, because sockets are a system-wide budget — chip takes several for mDNS, CASE and commissioning, then the SoftAP's DHCP server and the captive DNS responder, and the default httpd configuration asked for seven more. The setup AP and the captive DNS came up and the page behind them did not exist, which on a device with no stored Wi-Fi credentials means no way in at all. The ceiling is now lwIP's maximum of 16 and this server asks for four

  • OTA heap guard: the 50 kB threshold was measured on a build that boots with ~270 kB free. The Matter build starts with ~170 kB and would have refused every update on the firmware that most needs one, leaving a USB cable as the only way out (a316999)

  • Aliro delegate lifetime: DoorLockServer::InitEndpoint assigns the delegate unconditionally and the deprecated InitServer passes null, so whichever call landed second decided whether Aliro worked at all — silently (338c6a1)

  • Door Lock features are added in dependency order. esp-matter refuses to add USR unless a credential feature exists, and refuses by logging rather than by any return value, so the endpoint came up healthy while quietly missing the feature Aliro is defined in terms of (333515d)

  • pn532_begin is idempotent, so restarting the reader does not re-initialise an SPI host that is already up — which fails, and reads exactly like the PN532 having been unplugged

  • Removed the log page, /api/logs and the ring behind them: a 64-slot buffer of 160-byte lines plus a 32-line staging array, ~15.7 KB of DRAM held for the whole uptime on a board that had been caught unable to allocate a 1 KB request buffer. The serial port still prints everything

  • The WebSocket reconnect backs off exponentially instead of retrying every 3 seconds forever, which matters now the socket is gated

  • Web UI: ~76 KB of application partition freed by gzipping the embedded pages and serving them with Content-Encoding (e8e4fed)

  • Web UI: the OTA page follows HomeKey-ESP32's design rather than an invented one, and icon tiles appear only where that project uses them (ce03b3f, 262a04c)

Internal Changes

  • Access observers are a table rather than a single slot; MQTT and the Matter endpoint both need lock-state events
  • aliro_reader exposes its identity in the raw form other protocols want, and converts raw key material to the PEM the SDK expects, keeping esp_aliro_utils behind one component
  • app_config can store and erase PEM keys, so an identity provisioned over Matter lands where the browser flasher writes one
  • Kconfig: a symbol behind depends on does not exist when the dependency is false — the same trap twice, now documented where it bit (2e49c5b)
  • A component's CMakeLists cannot branch on its own CONFIG_ symbol: the pass that collects REQUIRES runs before component Kconfigs exist, so the sources built with no include path (ae0a802)
  • WHOLE_ARCHIVE on matter_lock, because esp-matter's cluster table calls back into our callbacks from a position the linker has already walked past (e9d37d6)

Build & CI Improvements

  • New matter-firmware workflow builds this project inside Espressif's esp-matter container, rather than grafting our driver onto their example (db13116)
  • The build fails if the application stops fitting a 1.875 MB OTA slot, and warns below 64 KB of headroom. Current: 1744 KB used, 175 KB spare
  • Artifacts now carry aliro_homekey.elf and the map, because this build strips assert messages and a panic prints bare addresses
  • tools/decode_backtrace.py turns those addresses back into functions and source lines using pyelftools — no toolchain, no multi-gigabyte install (02811bd)
  • tools/check_consistency.py now examines sdkconfig.matter, which had never been checked, and knows esp-matter's Kconfig namespaces (5dde756)
  • tools/package_firmware.sh takes a variant name, so a Matter image cannot overwrite an ordinary one in the same artifact

Documentation Updates

  • README: how to build with Matter, what it costs in flash, and why the phone ecosystems still refuse it
  • First bench test: bringing up the Matter build in risk order — the web UI is checked before anything Matter, because that is the seam where a failure needs a cable
  • Roadmap: milestone 3's "hard unknown" — how a wallet ends up holding a credential — is answered, and the part that is not is named

Known limitations

  • Apple, Google and Samsung will refuse to commission this. They require a device attestation certificate chaining to a root on the CSA's compliance ledger, which comes with certification. This image carries esp-matter's test credentials; chip-tool and Home Assistant accept them
  • The PN532 driver has never run against silicon. It is written, it compiles, and no card has ever been presented to it
  • The login is off until you turn it on, and over plain HTTP it raises the bar from "anyone who can reach the device" to "anyone who can also watch its traffic". TLS is the next step and this device has no certificate. There is no recovery if the password is lost, short of erasing the configuration over USB
  • The serial console is disabled in the Matter build, and there is no log page either. The serial port still prints everything; it just does not take commands
  • Aliro over BLE+UWB is not implemented — esp_aliro_lib is NFC-only today

Which file to flash

  • esp32.firmware.bin — the app partition on its own. This is the actual firmware, and the only file that goes over the air: upload it on the OTA page, no offset needed. Keeps stored configuration, and rolls back on its own if the new image cannot boot
  • esp32.firmware.factory.bin — bootloader, partition table, OTA data and the app, padded to the whole 4 MB chip. Flashed over USB at 0x0 for a fresh board. Wipes stored configuration, including Wi-Fi credentials and the reader identity

The web UI is compiled into the application rather than kept on a separate
filesystem partition, so one upload updates the reader and its interface
together — there is no second image to install.

The ELF for decoding a panic backtrace is not attached here; it is on the
matter-firmware workflow run that produced these binaries, kept for 30 days.