Skip to content

Commit 3e6a827

Browse files
committed
Option to reset the Matter state
1 parent 85bcf0b commit 3e6a827

1 file changed

Lines changed: 92 additions & 30 deletions

File tree

examples/esp/src/bin/light_wifi_persistent.rs

Lines changed: 92 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//! An example utilizing the `EmbassyWifiMatterStack` struct.
1+
//! An example utilizing the `EmbassyWifiMatterStack` struct
2+
//! and additionally persisting the `rs-matter` state to the NOR Flash.
23
//!
34
//! As the name suggests, this Matter stack assembly uses Wifi as the main transport,
45
//! and thus BLE for commissioning.
@@ -20,17 +21,19 @@ use core::pin::pin;
2021
use embassy_embedded_hal::adapter::BlockingAsync;
2122
use embassy_executor::Spawner;
2223

24+
use embassy_futures::select::{select, Either};
2325
use esp_alloc::heap_allocator;
2426
use esp_backtrace as _;
2527
use esp_bootloader_esp_idf::partitions::{
2628
read_partition_table, DataPartitionSubType, PartitionType, PARTITION_TABLE_MAX_LEN,
2729
};
30+
use esp_hal::gpio::{Input, InputConfig, Pull};
2831
use esp_hal::ram;
2932
use esp_hal::timer::timg::TimerGroup;
3033
use esp_metadata_generated::memory_range;
31-
3234
use esp_storage::FlashStorage;
33-
use log::info;
35+
36+
use log::{info, warn};
3437

3538
use rs_matter_embassy::epoch::epoch;
3639
use rs_matter_embassy::matter::crypto::{default_crypto, Crypto};
@@ -42,8 +45,10 @@ use rs_matter_embassy::matter::dm::devices::test::{
4245
};
4346
use rs_matter_embassy::matter::dm::devices::DEV_TYPE_ON_OFF_LIGHT;
4447
use rs_matter_embassy::matter::dm::{Async, Dataver, EmptyHandler, Endpoint, EpClMatcher, Node};
48+
use rs_matter_embassy::matter::error::Error;
4549
use rs_matter_embassy::matter::persist::KvBlobStore;
4650
use rs_matter_embassy::matter::utils::init::InitMaybeUninit;
51+
use rs_matter_embassy::matter::utils::select::Coalesce;
4752
use rs_matter_embassy::matter::{clusters, devices};
4853
use rs_matter_embassy::persist::SeqMapKvBlobStore;
4954
use rs_matter_embassy::stack::rand::reseeding_csprng;
@@ -86,6 +91,8 @@ const HEAP_SIZE: usize = 140 * 1024;
8691
const RECLAIMED_RAM: usize =
8792
memory_range!("DRAM2_UNINIT").end - memory_range!("DRAM2_UNINIT").start;
8893

94+
const RESET_SECS: u64 = 3;
95+
8996
esp_bootloader_esp_idf::esp_app_desc!();
9097

9198
#[esp_rtos::main]
@@ -154,33 +161,60 @@ async fn main(_s: Spawner) {
154161
let mut kv = get_persistent_store(peripherals.FLASH, stack.kv_store_buf().unwrap());
155162
stack.startup(&crypto, &mut kv).await.unwrap();
156163

157-
// Wrap the KV BLOB store as a shared reference, so that it can be used both by `rs-matter` and the user
158-
let kv = stack.create_shared_kv(kv).unwrap();
159-
160-
// Run the Matter stack with our handler
161-
// Using `pin!` is completely optional, but reduces the size of the final future
162-
//
163-
// This step can be repeated in that the stack can be stopped and started multiple times, as needed.
164-
let matter = pin!(stack.run_coex(
165-
// The Matter stack needs to instantiate an `embassy-net` `Driver` and `Controller`
166-
EmbassyWifi::new(
167-
EspWifiDriver::new(peripherals.WIFI, peripherals.BT),
168-
weak_rand,
169-
true, // Use a random BLE address
170-
stack,
171-
),
172-
// The crypto provider
173-
&crypto,
174-
// Our `AsyncHandler` + `AsyncMetadata` impl
175-
(NODE, handler),
176-
// The Matter stack needs a blob store to store its state
177-
&kv,
178-
// No user future to run
179-
(),
180-
));
181-
182-
// Run Matter
183-
matter.await.unwrap();
164+
if stack.is_commissioned() {
165+
info!(
166+
"To reset, press and hold the Boot Mode pin (GPIO9) for {} or more seconds",
167+
RESET_SECS
168+
);
169+
}
170+
171+
{
172+
// Wrap the KV BLOB store as a shared reference, so that it can be used both by `rs-matter` and the user
173+
let kv = stack.create_shared_kv(&mut kv).unwrap();
174+
175+
// Run the Matter stack with our handler
176+
// Using `pin!` is completely optional, but reduces the size of the final future
177+
//
178+
// This step can be repeated in that the stack can be stopped and started multiple times, as needed.
179+
let mut matter = pin!(stack.run_coex(
180+
// The Matter stack needs to instantiate an `embassy-net` `Driver` and `Controller`
181+
EmbassyWifi::new(
182+
EspWifiDriver::new(peripherals.WIFI, peripherals.BT),
183+
weak_rand,
184+
true, // Use a random BLE address
185+
stack,
186+
),
187+
// The crypto provider
188+
&crypto,
189+
// Our `AsyncHandler` + `AsyncMetadata` impl
190+
(NODE, handler),
191+
// The Matter stack needs a blob store to store its state
192+
&kv,
193+
// No user future to run
194+
(),
195+
));
196+
197+
// Run Matter and also wait for a reset signal
198+
let mut wait_reset = pin!(wait_pin_low(Input::new(
199+
peripherals.GPIO9,
200+
InputConfig::default().with_pull(Pull::Down)
201+
)));
202+
203+
select(&mut matter, &mut wait_reset)
204+
.coalesce()
205+
.await
206+
.unwrap();
207+
}
208+
209+
// If we get here, with no errors, this means the user is willing to reset the storage
210+
// by holding the BOOT pin low 3 or more seconds
211+
warn!("Resetting storage");
212+
213+
stack.reset(kv).await.unwrap();
214+
215+
warn!("Rebooting...");
216+
217+
esp_hal::system::software_reset()
184218
}
185219

186220
/// Endpoint 0 (the root endpoint) always runs
@@ -230,3 +264,31 @@ fn get_persistent_store<'d>(
230264

231265
SeqMapKvBlobStore::new(BlockingAsync::new(flash), start..end)
232266
}
267+
268+
async fn wait_pin_low(mut pin: Input<'_>) -> Result<(), Error> {
269+
loop {
270+
pin.wait_for_low().await;
271+
272+
// Debounce
273+
embassy_time::Timer::after_millis(50).await;
274+
275+
if pin.is_low() {
276+
warn!(
277+
"Detected Boot Mode pin low, keep it low for {} more seconds to reset the storage",
278+
RESET_SECS
279+
);
280+
281+
let result = select(
282+
pin.wait_for_high(),
283+
embassy_time::Timer::after_secs(RESET_SECS),
284+
)
285+
.await;
286+
287+
if matches!(result, Either::Second(())) {
288+
break;
289+
}
290+
}
291+
}
292+
293+
Ok(())
294+
}

0 commit comments

Comments
 (0)