All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Implement MQTT outbox limit and get_outbox_size()
- Added argument
subprotocol_listtows_handlerto allow subprotocols to be supported by WebSockets
- Fix wrong conversion from
ScanTypetou32in Wi-Fi configuration - Fix wrong BT configuration version on the c6 (issue #556)
- Fix inconsistent mutability in NVS (#567)
- Fix #570 (c_char vs i8 mismatch on newer rustc toolchains)
- OTA: New method -
EspFirmwareInfoLoad::fetch_native- returning the full native ESP-IDF image descriptor structures - Added
use_serdefeature, which enables theuse_serdefeature ofembedded-svccrate, allowing to deserialize configuration structs. - OTA: Allow specifying image size to speed up erase
- Bluetooth: New methods
EspBleGap::start_scanningandEspBleGap::stop_scanning - New example,
bt_ble_gap_scannerto demonstrate usage of added ble scanning methods - Add #[must_use] annotations to event loop types with drop handlers.
- New
embassy-time-driverimplementation compatible withembassy-time-driverV0.2 (#548)
- New example,
wifi_dhcp_with_hostnameto demonstrate setting a custom hostname when establishing a DHCP connection
- Fix ambiguous name error (a compilation issue when the NimBLE component is enabled in esp-idf-sys)
EspFirmwareInfoLoaderuseEspFirmwareInfoLoadinstead
- Wifi event details (#455)
- Add poll_read/write and implement futures_io::AsyncRead/Write for EspAsyncTls (#488)
- Support for LittleFS (#498)
- Change default eth key (#502)
- ESP IDF Partitions API (#511)
- Expose src_addr and dst_addr in espnow recv cb (#525)
- Add
corefield tohttp::server::Configurationto control which CPU core runs the HTTP server task
- Compatibility with ESP-IDF v5.3.X
- feat(eth): Implement alternative polling mode (#452)
- SD Card driver; SD Card host drivers (SPI and SDMMC) (#454)
- Make EspAsyncMqttClient::wrap public. (#462)
- Netif-driver support
- Netif PPP (#473)
- Added http_local_network_server example (#471)
- Added esp_wifi_sta_get_rssi function in EspWifi (#478)
- Expose esp_mqtt_client_set_uri. Fix issue #481. (#482)
- Option to explicitly initialize the netif stack (NetifStack::initialize)
- Support for Thread (#484)
- Enable usage of
esp_idf_log_timestamp_rtosfor ms since boot andesp_idf_log_timestamp_source_systemfor system time in rust logging (#494) - Document OTA API (#500)
- Add option to specify initial caps for the MQTT async adaptor vectors
- Allow using esp timer with skip_unhandled_events (#526)
- OTA - Implements a new type
EspFirmwareInfoLoadthat has a reduced memory consumption (#531) - Added set_promiscuous function in EthDriver (#246)
- Added set_promiscuous, is_promiscuous functions in WifiDriver (#246)
- Blocking and buffered StdIo (#541) - i.e. easy reading/input from
std::io::stdin - Added source_ipv4, source_ipv6 function in EspHttpRawConnection (#538)
- The alloc::Vec version stomps the scan state from Done to Idle. (#459)
- Logging - Fix set_target_level (#458)
- Make async mqtt client implement Send. (#461)
- Implement Sync for EspMqttEvent. (#463)
- Avoid potential memory leak when dropping mqtt clients (#464)
- Filter asynchronous events (#466)
- Remove unnecessary buffer draining in HTTP client example (#470)
- Fixed: EspLogger is not extensible
- Fix incorrect key variable being logged for the struct storage for raw NVS access example (#479)
eth_esp32_emac_default_config- 5.3 compatibility- Fix "esp32c2 use example http_sw_server report err ESP_ERR_HTTPD_TASK"
- Added IP_EVENT_ETH_LOST_IP to deserialize list (#491)
- examples/http_ws_server.rs: fix string decoding (#510)
- Bugfix: crash on MQTT async client restart
- Fix missing newline if CONFIG_LOG_COLORS=n is set (#521)
- gatekeep mdns ipv6 behind feature flag (#523)
- Fix emac_rx stack overflow when log verbosity is increased (#535)
- Bluetooth: The experimental Bluedroid support did not compile on esp32c2, esp32h2 and esp32c6 (#447)
ESP-IDF v4.4 Please start upgrading to ESP-IDF v5.
- removed ESP-IDF v4.3 support, including mostly conditional compilations. (#431)
- wifi: now can use embedded-svc PmfConfiguration, ScanMethod, and ScanSortMethod in ClientConfiguration. (#381)
- wifi: The WifiEvent's ApStaConnected and ApStaDisconnected were changed to include the idf's wifi_event. (#396)
- eth: callbacks now use newly added EthFrames instead of &[u8]. (#406)
- wifi: callbacks now use newly added WifiFrames instead of &[u8]. (#406)
- http_server: Configuration now allows for setting the ctrl_port. (#427)
- http_server: UB fix:
handler,fn_handlerandhandler_chainall now only accept'staticcallbacks, which is the only safe option in the presence ofcore::mem::forgeton the HTTP server. All of those have the previous behavior preserved in the form ofunsafe*_nonstaticvariants which were added. (#437) - tls: negotiate now returns the new CompletedHandshake struct instead of (). (#428)
- wifi: Remove AUTOUP as the default flag on ClientConfiguration:Fixed. (#426)
- tls: Allow TLS negotiation on a multi-threaded executor. (#432)
- MSRV: 1.77 (due to
core::netwhich is re-exported byembedded-svcand is stable since Rust 1.77)
- tls: Support for TLS server. (#368)
- ws: expose crt_bundle_attach to EspWebSocketClientConfig. (#391)
- ping: can now be used with disabled IPv6. (#418)
- wifi: EspWifi's wrap_all method now supports only wrapping sta if softAp is disabled. (#376)
- sd: New SD mmc & spi drivers. Check out the sd_mmc and sd_spi examples. (#422)
- fs: new wrapper implementation around fat. (#422)
- tls: Make EspTls and EspAsyncTls Send when possible. (#429)
- ble/gatt: New BLE GATT server support using Bluedroid. Check out the bt_gatt_server example. (#421)
- nvs: encrypted partition could not find partition by name. (#387)
- ota: handle partition errors gracefully. (#393)
- http_client: flush responses to avoid repeated request failures. (#404)
- eth: missing error return inside the rx_callback function. (#414)
- wifi: AccessPointConfiguration now correctly limits max_connections. (#426)
- wifi: Fix WPS regression around null termination of ssid/password. (#379)
- Compatibility with ESP-IDF v5.3 (pre-release): various fixes such that esp-idf-svc can be used against the latest esp-idf versions. (#434)
- Disable the
esp_idf_svc::io::vfsmodule if the ESP IDF VFS component is not enabled either - Bugfix / async MQTT: The internal
Unblockerutility was missingdropand therefore did not delete its task properly, resulting in a crash when the async MQTT client is dropped - #357 -
AsyncWifiwas notSendanymore (regression).Sendrestored. - #356 - Change payload of
EspEventPostDatafrom&[u32]to&[u8] - #357 - Restore
SendforAsyncWifi - #369 - (Crash) Restore the drop impl EspMqttClient
- #370 - (Deadlock) Fix a deadlock when dropping an MQTT client in the presence of a blocking EspMqttConnection
- Fix clippy duplicate imports warnings with latest 1.78 nightly
- New examples:
- MQTT client (blocking and async)
- TLS (async; blocking already exists)
- Event loop (blocking and async)
- Timers (blocking and async)
- SPI Ethernet (async; a blocking example for RMII Ethernet already exists)
- TCP client and server (blocking and async)
- SNTP service
- Websocket client (blocking)
- Breaking changes in module
eventloop:- Async send and receive functionality now implemented directly on the
esp-idf-svcevent loop types, as theembedded_svc::utils::asyncifymodule is now gone - Types
EspTypedEventLoopandEspPostboxare now retired. UseEspEventLoopdirectly, as it has the same functionality EspEventFetchDatarenamed toEspEvent; bothEspEventandEspEventPostDatanow lifetimed instead of using raw pointers- Trait
EspTypedEventSourceis renamed toEspEventSourceand marked as unsafe (i.e., implementors should dounsafe impl EspTypedEventSource for ...); check the documentation of the trait for justification - Types
EspTypedEventDeserializerandEspTypedEventSerializerrenamed to justEspEventSerializerandEspEventDeserializer; more importantly, their payload is now modeled using a lifetimed GAT member calledData<'a>; this allows deserializers to implement zerocopy deserialization by referencing the event payload which is owned by the event loop; allesp-idf-svcdeserializers (notably -WifiEventandIpEvent) are now implemented with zerocopy, thus reducing the pressure on the system event loop task stack size - The
EspEventtype is now also a dummy (no op)EspEventDeserializer; theEspEventPostDatatype is now also a dummy (no op)EspEventSerializer - Because of the above changes, methods
subscribe*andpost*are now slightly less convenient to use in that they need the (de)serializer specified using turbofish syntax, i.e.event_loop.subscribe::<WifiEvent, _>(...); this is so because these methods no longer require (and cannot require - due to the lifetimed GAT from above)where P: EspEvent(De)serializer<P>, i.e. the event type itself to implement the (de)sderializer, even if all event types provided byesp-idf-svcdo that - The
post*andspinmethods now take a timeout of typeTickType_tas everywhere rather than the complexOption<Duration>
- Async send and receive functionality now implemented directly on the
- Breaking changes in module
http::server:- Due to the breaking change in
embedded_svc::http::server, whereasHandlerErrorandHandlerResultwere removed, these types are no longer used in theembedded_svc::http::servermodule either. Check the Changelog ofembedded_svcfor more details
- Due to the breaking change in
- Breaking change in module
timer: all async timer functionality now implemented directly on theesp-idf-svctimer types, as theembedded_svc::utils::asyncifymodule is now gone - Breaking changes in module
mqtt::client:- All async send/receive functionality now implemented directly on the
esp-idf-svcMQTT types, as theembedded_svc::utils::asyncifymodule is now gone - Changes induced by breaking changes in
embedded_svc::mqtt::clientAPI contract:- All event conversion logic now retired, significantly simplifying the type signatures of
EspMqttClientandEspMqttConnection, as well as the number of offered constructors - For MQTT events, user always gets an instance of
EspMqttEventwhich implements theembedded_svc::mqtt::client::Eventtrait - valid for both callback-based event processing as well as for connection-based blocking and asynchronous event processing
- All event conversion logic now retired, significantly simplifying the type signatures of
- All async send/receive functionality now implemented directly on the
- Breaking change:
AsyncEspTlsrenamed toEspAsyncTls - MSRV 1.75; remove the nightly feature flag from all async trait implementations
- Update public dependency
heaplessto 0.8 - Remove dependency on
embassy-timeand replace it with a dependency onembassy-time-driver; get rid of the custom embassy time queue as it was anyway re-implementing something like a generic timer queue, which is available in theembassy-timecrate (with its featuregeneric-queueenabled) - #316 - breaking change addressing a typo -
http::server::Configuration::max_resp_handlersrenamed tohttp::server::Configuration::max_resp_headers - #319 - Set default TTL in
EspPingto 64 - #322 - Fix MQTT PSK code (did not compile)
- #323 - ETH example with a statically configured IP
- #324 - New methods in
EspWifito swap STA and AP netifs separately from each other - #326 - logging from multiple threads in Rust/ESP-IDF no longer results in intermixed logs
- #331 - Add support for WPS
- BREAKING CHANGE IN A PATCH RELEASE DUE TO DISCOVERED UB: All constructors and methods in the Classic BT services, as well as in
services
EspNow, driverEthDriver,EventLoop,Wait,EspHttpServer,EspMqttClient,EspSntp,EspTimerService, driverWifiDriverandEspWebSocketClientno longer accept non-static callbacks, as these lead to UB / crash when the service/driver/subscription is forgotten with e.g.core::mem::forget. Since local borrows are a very useful feature however, these are still allowed via the newly-introduced andunsafemethods/constructors that follow the naming pattern of the safe methods/constructors, but with a_nonstaticsuffix attached.
- Remove dependency on
AtomicU64which is no longer supported by the upstream*-espidftargets - HTTP client: support for chunked encoding of POST requests
- Compatibility with
embedded-svc0.26.1
- MSRV raised to 1.71
- New
experimentalmodule -bt- providing Bluetooth support based on the ESP-IDF Bluedroid implementation- Only classic BT supported for now (on the ESP32) with the following profiles: A2DP sink, AVRC controller, HFP client, GAP
- BLE support in the works, but not buildable yet
- TLS over TCP/IP support in the
tlsmodule viaEspTlsand (for async mode)AsyncEspTls - PSK support for
mqtt - Dependencies
esp-idf-sysandesp-idf-halare now re-exported asesp_idf_svc::sysandesp_idf_svc::hal - Upgraded to
embedded-svc0.26 - OTA: New method:
EspOta::finishthat allows to postpone/avoid setting the updated partition as a boot one - Breaking change: OTA:
EspOtaUpdatenow parametric over the lifetime of a mutable reference toEspOtaand returned by value - Breaking change: OTA:
EspOtaUpdate::abortandEspOtaUpdate::completenow takeselfinstead of&mut self - Breaking change: HTTP server: Scoped handlers; handlers now need to live only as long as the
EspHttpServerinstance. Therefore,EspHttpServeris now lifetimed:EspHttpServer<'a> - Breaking change: HTTP server:
EspHttpRequestrenamed toEspHttpRawConnection - Breaking change: WS client: Scoped handler; the event handler now needs to live only as long as the
EspWebSocketClientinstance. Therefore,EspWebSocketClientis now lifetimed:EspWebSocketClient<'a> - Breaking change: EspTimerService: scoped handler: the timer callback now only needs to live as long as the returned
EspTimerinstance. Therefore,EspTimeris now lifetimed:EspTimer<'a> - Breaking change: EspEventLoop: scoped handler: the subscription callback now only needs to live as long as the returned
EspSubscriptioninstance. Therefore,EspSubscriptionis now lifetimed:EspSubscription<'a, ...> - Breaking change: MQTT client: Scoped handler; the event handler now needs to live only as long as the
EspMqttClientinstance. Therefore,EspMqttClientis now lifetimed:EspMqttClient<'a, ...> - Breaking change: EspNow client: Scoped handlers; the event handlers now need to live only as long as the
EspNowinstance. Therefore,EspNowis now lifetimed:EspNow<'a> - Breaking change: Sntp client: Scoped handler; the event handler now needs to live only as long as the
EspSntpinstance. Therefore,EspSntpis now lifetimed:EspSntp<'a> - Breaking change (bugfix): Ping client:
EspPing::ping_detailsnow takes aFnMutcallback, however the callback needs to beSend - Breaking change: Removed the deprecated module
httpdand the dependency onanyhow - Breaking change: module
notifyremoved as it was rarely - if ever - used, and there is a simplerhal::task::notificationmodule now - Deprecated: Using ESP-IDF 4.3 is now deprecated and all special cfg flags will be removed in the next release
- EspMdns::query crashes when no services are found #279
- OTA: get_running_slot was wrongly returning the boot slot
- Workaround issue 11921 in ESP IDF (new member of struct
wifi_scan_config_t) - Make all conversions to CString fallible rather than panic-ing
- Bugfixes in HTTPD WS support: Allow calls with a zero-length buffer
- Added docstrings for wifi module (#262)
- MSRV 1.66
- Support for ESP IDF 5.0, 5.1 and 5.2 (master)
- Remove the
experimentalstatus from all formerly experimental features - Remove the
nightlyfeature flag guard from allasyncifymodules as Rust GATs are stable now - Async and blocking APIs for
Wifi,EthandEspNetifthat abstract away the ESP IDF system event loop (for easier initial configuration) - API breakage innetif EthSPI driver rebased on top ofesp-idf-hal'sSpiDeviceDriver; it can now either borrow or own the SPI device driver (API breakage)Ethdriver now supports SPI bus sharing with other SPI devices (API breakage)NVS- additional APIs that support the serde format of the ESP IDF NVS C codeSNTP- new, callback APIlog- support for setting target level per moduleOTA- small API extensionsnetif- compilation errors when PPP & SLIP support is enabled are addressed- HTTP client & server - various bugfixes
EspError::from_infallible
HTTP server:
- Compatibility with
embedded-svcV0.24 - New function -
fn_handlerthat addresses HRTB lifetime issues when converting a Fn closure to aHandlerinstance - Remove
EspHttpFnTraversableChain; it is not necessary, now that thefn_handlerfunction from above does exist
Rebase on top of esp-idf-sys 0.32:
- Retire any usages of
esp-idf-sys::c_typesin favor ofcore::ffi - Remove the
cstr_coredependency asCstrandCStringare now part of Rust core - Remove casts from
usizetou32and back now thatesp-idf-sysis compiled with--size_t-is-usizeenabled
Patch releases:
- Eth driver:
- SPI drivers now work with ESP IDF 5+
- DMA channel is now configurable
- Clippy fixes
Patch releases to fix compilation errors under no_std.
Release 0.43 is a backwards-incompatible release where almost all services were touched in one way or another.
The main themes of the 0.43 release are:
- Public API
- Separate the notions of using a "nightly" compiler (which is a precondition for all async support) from "experimental" features, which might or might not be async-related
- Expose access to the wrapped ESP IDF services / drivers
- Wifi & Eth: separate layer 2 (ethernet) from layer 3 (IP)
- Http client & server: implement the new traits from
embedded-svc - Merge the
nvs_storagemodule intonvs - Support for the
embassy-timecrate by providing alarm implementation - Support for the
embassy-timecrate by providing timer queue implementation
In addition to implementing the embedded-svc traits where possible, all services now have public API. While the public API loosely follows the APIs from embedded-svc, it deviates where appropriate so that the native underlying ESP IDF service is better utilized.
These public APIs mean that the user is no longer required to depend on the embedded-svc crate so as to consume the esp-idf-svc services.
Consuming the services via the embedded-svc traits is now only necessary when the user is targetting cross-platform portability of their application code.
All services now implement the Handle trait which does provide a reference to the native underlying ESP IDF service or driver. This is useful when the Rust wrapper for the service does not expose a particular functionality, as in that case, users can still call the functionality by using the raw esp-idf-svc bindings for the service.
The Wifi and Ethernet drivers are now split into two separate structures:
WifiDriver/EthDriver- these are layer 2 (Ethernet) drivers which follow all the conventions of the other drivers in theesp-idf-halcrate, including the need to own or mutably borrow the actual petihperal (the Wifi modem peripheral or the RMII / SPI peripheral fromesp-idf-hal). They are however part ofesp-idf-svcas this is better aligned with their native ESP IDF counterparts, which actually do use/rely on certain ESP IDF services, like the event loop and NVS storage, which - being services - are also exposed as part ofesp-idf-svc, and not as part ofesp-idf-hal. These drivers implement theWifiandEthtraits respectively, which were redesigned to not have any IP-related semantics. Users are allowed to use the Layer 2 drivers directly by providing their own custom RX callbacks, thus completely bypassing the ESP IDF LwIP IP & Netif layer (i.e. withsmoltcpor other 3rd party IP stack)EspWifi/EspEth- these are layer 3 (IP) + layer 2 (Ethernet) services, which - on construction - are expected to own aWifiDriver/EthDriver- either by constructing it themselves, or by the user passing the driver. These services "glue" the ESP IDF IP & Netif layer (EspNetif) with the ethernet layer provided by the drivers. These services also implement theWifi/Ethtraits, as they are wrapping Layer 2 functionality anyway. The Layer 3 functionality (configuring the network interface as well as fetching IP-related information from the network interfaces) however uses custom methods on the services' themselves and is not (yet) abstracted usingembedded-svctraits.
Additionally, the Wifi and Eth trait implementations now provide finer grained control over the behavior of their drivers / services in that users should explicitly call start/stop to start/stop the driver, as well as connect/disconnect (for the Wifi driver in STA mode) to connect to an access point. While this makes the driver configuration a bit more involved, these changes provide the necessary flexibility for some corner use cases:
- When the Wifi driver is used together with the
EspNowESP NOW service, there is no need to actuallyconnectthe driver at all, which is now possible - More complex connect/disconnect schemes can now be implemented by users, for roaming or for reacting in case the Wifi connection is lost
Subject says it all, so to say.
- The previous distinction of two separate modules was awkward and is thus removed
- The other notable change here is that the ESP IDF implementation actually only implements the
RawStoragetrait, which provides facilities for reading / writing blobs. It is up to the user to layer aStorageimplementation on top of theRawStorageimplementation, but the benefit of that is that user is in control of how their structures are serialized/deserialized into binary. To ease the layering, users may take advantage of theStorageImplstructure fromembedded-svcand only provide aSerdetrait implementation which abstracts away the concrete Rust SerDe implementation (i.e.serde-json,postcard, etc.)
esp-idf-svc provides an implementation of embassy-time's alarm interface (the Driver trait), which is implemented in terms of the ESP IDF Timer service (also exposed in the timer module of esp-idf-svc).
To use this feature, users need to enable the embassy-time-driver Cargo feature.
esp-idf-svc does provide a custom embassy-time Timer Queue implementation (also implemented in terms of the ESP IDF Timer service), even though in the meantime embassy-time features a generic timer queue which works everywhere and can also be used. This custom timer queue does not rely on the alarms interface provided by the embassy-time crate (see the previous section).
The one major difference between embassy-time's generic timer queue, and the one provided by esp-idf-svc is that the latter has a slightly lower latency in that it does support the CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y ESP IDF configuration parameter. When this parameter is enabled, the esp-idf-svc timer queue does not use the ESP IDF Timer Service dispatch task/thread and notifies the executor about due timers directly from the ISR routine. When this parameter is not enabled, the esp-idf-svc timer queue has no benefits compared to the generic timer queue in embassy-time.
NOTE:
- The
esp-idf-svctimer queue should only be used with async executors that are ISR safe, in that they can be awoken from an ISR.edge-executoris such an executor. embassy-executoris currently NOT ISR safe, because it relies - for its synchronization - on thecritical-sectioncrate, yet the critical section implementation that thecritical-sectioncrate uses on top ofesp-idf-halis based on a FreeRTOS mutex, and NOT on a disable-all-interupts ISR-safe implementation (that is, unless the user has configured a more elaborate setup with their own critical section implementation). On the other hand,embassy-executorhas its own highly optimized timer queue which should probably be used anyway and is enabled by default- All other executors can just use the generic timer queue implementation which is built-in in the
embassy-timecrate
To use this feature, users need to enable the embassy-time-isr-queue Cargo feature.