@@ -14,6 +14,7 @@ use embassy_time::{Instant, Timer};
1414use esp_backtrace as _;
1515use esp_hal_wifimanager:: { Nvs , WIFI_NVS_KEY } ;
1616use esp_storage:: FlashStorage ;
17+ use esp_wifi:: esp_now:: { EspNowManager , EspNowSender } ;
1718use state:: { ota_state, sleep_state, GlobalState , GlobalStateInner , SavedGlobalState , Scene } ;
1819use structs:: ConnSettings ;
1920use utils:: { logger:: FkmLogger , set_brownout_detection} ;
@@ -52,6 +53,16 @@ pub fn custom_rng(buf: &mut [u8]) -> Result<(), getrandom::Error> {
5253}
5354getrandom:: register_custom_getrandom!( custom_rng) ;
5455
56+ const ESP_NOW_DST : & [ u8 ; 6 ] = & [ 156 , 158 , 110 , 52 , 70 , 200 ] ;
57+ macro_rules! mk_static {
58+ ( $t: ty, $val: expr) => { {
59+ static STATIC_CELL : static_cell:: StaticCell <$t> = static_cell:: StaticCell :: new( ) ;
60+ #[ deny( unused_attributes) ]
61+ let x = STATIC_CELL . uninit( ) . write( ( $val) ) ;
62+ x
63+ } } ;
64+ }
65+
5566#[ esp_hal_embassy:: main]
5667async fn main ( spawner : Spawner ) {
5768 let peripherals = esp_hal:: init ( {
@@ -176,101 +187,142 @@ async fn main(spawner: Spawner) {
176187 }
177188 }
178189
179- let wifi_res = esp_hal_wifimanager:: init_wm (
180- wm_settings,
181- & spawner,
182- #[ cfg( feature = "qa" ) ]
183- None ,
184- #[ cfg( not( feature = "qa" ) ) ]
185- Some ( & nvs) ,
186- board. rng ,
187- board. timg0 . timer0 ,
188- board. radio_clk ,
189- board. wifi ,
190- board. bt ,
191- Some ( wifi_setup_sig) ,
192- )
193- . await ;
194-
195- let Ok ( mut wifi_res) = wifi_res else {
196- log:: error!( "WifiManager failed!!! Restarting in 1s!" ) ;
197- Timer :: after_millis ( 1000 ) . await ;
198- esp_hal:: system:: software_reset ( ) ;
199- } ;
190+ #[ cfg( feature = "esp_now" ) ]
191+ {
192+ let init = & * mk_static ! (
193+ esp_wifi:: EspWifiController <' static >,
194+ esp_wifi:: init( board. timg0. timer0, board. rng. clone( ) , board. radio_clk) . unwrap( )
195+ ) ;
196+
197+ let ( manager, tx, mut rx) = esp_wifi:: esp_now:: EspNow :: new ( & init, board. wifi )
198+ . unwrap ( )
199+ . split ( ) ;
200+
201+ _ = manager. set_power_saving ( esp_wifi:: config:: PowerSaveMode :: None ) ;
202+ //_ = manager.set_rate(esp_wifi::esp_now::WifiPhyRate::RateMax);
203+ _ = manager. set_pmk ( & [ 69 , 4 , 2 , 0 , 1 , 2 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
204+
205+ spawner. must_spawn ( bc_test_task ( tx, manager) ) ;
206+ let mut last_counter = 0 ;
207+ loop {
208+ let recv = rx. receive_async ( ) . await ;
209+ log:: info!( "ESP_NOW frame recv: {:?}" , recv. info) ;
210+ log:: info!( "{:?}" , recv. data( ) ) ;
211+
212+ if & recv. info . dst_address == ESP_NOW_DST {
213+ if recv. data ( ) . len ( ) == 16 {
214+ let counter = u128:: from_be_bytes ( recv. data ( ) . try_into ( ) . unwrap ( ) ) ;
215+ if counter - last_counter == 0 {
216+ log:: warn!( "First packet?" ) ;
217+ } else if counter - last_counter > 1 {
218+ log:: error!( "PACKET LOST!" ) ;
219+ }
220+
221+ last_counter = counter;
222+ }
223+ }
224+ }
225+ }
200226
201- #[ cfg( feature = "qa" ) ]
202- crate :: qa:: send_qa_resp ( crate :: qa:: QaSignal :: WifiSetup ) ;
203-
204- let conn_settings: ConnSettings = wifi_res
205- . data
206- . take ( )
207- . and_then ( |d| serde_json:: from_value ( d) . ok ( ) )
208- . unwrap_or_default ( ) ;
209-
210- let mut parse_retry_count = 0 ;
211- let ws_url = loop {
212- let url = if conn_settings. mdns || conn_settings. ws_url . is_none ( ) || parse_retry_count > 0 {
213- log:: info!( "Starting mdns lookup..." ) ;
214- global_state. state . lock ( ) . await . scene = Scene :: MdnsWait ;
215- let mdns_res = mdns:: mdns_query ( wifi_res. sta_stack ) . await ;
216- log:: info!( "Mdns result: {:?}" , mdns_res) ;
217-
218- mdns_res. to_string ( )
219- } else {
220- conn_settings. ws_url . clone ( ) . expect ( "" )
227+ #[ cfg( not( feature = "esp_now" ) ) ]
228+ {
229+ let wifi_res = esp_hal_wifimanager:: init_wm (
230+ wm_settings,
231+ & spawner,
232+ #[ cfg( feature = "qa" ) ]
233+ None ,
234+ #[ cfg( not( feature = "qa" ) ) ]
235+ Some ( & nvs) ,
236+ board. rng ,
237+ board. timg0 . timer0 ,
238+ board. radio_clk ,
239+ board. wifi ,
240+ board. bt ,
241+ Some ( wifi_setup_sig) ,
242+ )
243+ . await ;
244+
245+ let Ok ( mut wifi_res) = wifi_res else {
246+ log:: error!( "WifiManager failed!!! Restarting in 1s!" ) ;
247+ Timer :: after_millis ( 1000 ) . await ;
248+ esp_hal:: system:: software_reset ( ) ;
221249 } ;
222250
223- let ws_url = WsUrl :: from_str ( & url) ;
224- match ws_url {
225- Some ( ws_url) => break WsUrlOwned :: new ( & ws_url) ,
226- None => {
227- parse_retry_count += 1 ;
228- log:: error!( "Mdns parse failed! Retry ({parse_retry_count}).." ) ;
229- Timer :: after_millis ( 1000 ) . await ;
230- if parse_retry_count > 3 {
231- log:: error!( "Cannot parse wsurl! Reseting wifi configuration!" ) ;
232- _ = nvs. invalidate_key ( WIFI_NVS_KEY ) . await ;
251+ #[ cfg( feature = "qa" ) ]
252+ crate :: qa:: send_qa_resp ( crate :: qa:: QaSignal :: WifiSetup ) ;
253+
254+ let conn_settings: ConnSettings = wifi_res
255+ . data
256+ . take ( )
257+ . and_then ( |d| serde_json:: from_value ( d) . ok ( ) )
258+ . unwrap_or_default ( ) ;
259+
260+ let mut parse_retry_count = 0 ;
261+ let ws_url = loop {
262+ let url =
263+ if conn_settings. mdns || conn_settings. ws_url . is_none ( ) || parse_retry_count > 0 {
264+ log:: info!( "Starting mdns lookup..." ) ;
265+ global_state. state . lock ( ) . await . scene = Scene :: MdnsWait ;
266+ let mdns_res = mdns:: mdns_query ( wifi_res. sta_stack ) . await ;
267+ log:: info!( "Mdns result: {:?}" , mdns_res) ;
268+
269+ mdns_res. to_string ( )
270+ } else {
271+ conn_settings. ws_url . clone ( ) . expect ( "" )
272+ } ;
273+
274+ let ws_url = WsUrl :: from_str ( & url) ;
275+ match ws_url {
276+ Some ( ws_url) => break WsUrlOwned :: new ( & ws_url) ,
277+ None => {
278+ parse_retry_count += 1 ;
279+ log:: error!( "Mdns parse failed! Retry ({parse_retry_count}).." ) ;
233280 Timer :: after_millis ( 1000 ) . await ;
281+ if parse_retry_count > 3 {
282+ log:: error!( "Cannot parse wsurl! Reseting wifi configuration!" ) ;
283+ _ = nvs. invalidate_key ( WIFI_NVS_KEY ) . await ;
284+ Timer :: after_millis ( 1000 ) . await ;
234285
235- esp_hal:: system:: software_reset ( ) ;
236- }
286+ esp_hal:: system:: software_reset ( ) ;
287+ }
237288
238- continue ;
289+ continue ;
290+ }
239291 }
240- }
241- } ;
292+ } ;
242293
243- utils:: backtrace_store:: read_saved_backtrace ( ) . await ;
294+ utils:: backtrace_store:: read_saved_backtrace ( ) . await ;
295+
296+ let ws_sleep_sig = Rc :: new ( Signal :: new ( ) ) ;
297+ spawner. must_spawn ( ws:: ws_task (
298+ wifi_res. sta_stack ,
299+ ws_url,
300+ global_state. clone ( ) ,
301+ ws_sleep_sig. clone ( ) ,
302+ ) ) ;
303+ spawner. must_spawn ( logger_task ( global_state. clone ( ) ) ) ;
304+
305+ set_brownout_detection ( true ) ;
306+ global_state. state . lock ( ) . await . scene = Scene :: WaitingForCompetitor ;
307+ if let Some ( saved_state) = SavedGlobalState :: from_nvs ( & nvs) . await {
308+ global_state
309+ . state
310+ . lock ( )
311+ . await
312+ . parse_saved_state ( saved_state) ;
313+ }
244314
245- let ws_sleep_sig = Rc :: new ( Signal :: new ( ) ) ;
246- spawner. must_spawn ( ws:: ws_task (
247- wifi_res. sta_stack ,
248- ws_url,
249- global_state. clone ( ) ,
250- ws_sleep_sig. clone ( ) ,
251- ) ) ;
252- spawner. must_spawn ( logger_task ( global_state. clone ( ) ) ) ;
253-
254- set_brownout_detection ( true ) ;
255- global_state. state . lock ( ) . await . scene = Scene :: WaitingForCompetitor ;
256- if let Some ( saved_state) = SavedGlobalState :: from_nvs ( & nvs) . await {
257- global_state
258- . state
259- . lock ( )
260- . await
261- . parse_saved_state ( saved_state) ;
262- }
315+ let mut last_sleep = false ;
316+ loop {
317+ Timer :: after_millis ( 100 ) . await ;
318+ if sleep_state ( ) != last_sleep {
319+ last_sleep = sleep_state ( ) ;
320+ ws_sleep_sig. signal ( last_sleep) ;
263321
264- let mut last_sleep = false ;
265- loop {
266- Timer :: after_millis ( 100 ) . await ;
267- if sleep_state ( ) != last_sleep {
268- last_sleep = sleep_state ( ) ;
269- ws_sleep_sig. signal ( last_sleep) ;
270-
271- match last_sleep {
272- true => wifi_res. stop_radio ( ) ,
273- false => wifi_res. restart_radio ( ) ,
322+ match last_sleep {
323+ true => wifi_res. stop_radio ( ) ,
324+ false => wifi_res. restart_radio ( ) ,
325+ }
274326 }
275327 }
276328 }
@@ -313,3 +365,25 @@ async fn logger_task(global_state: GlobalState) {
313365 }
314366 }
315367}
368+
369+ #[ cfg( feature = "esp_now" ) ]
370+ #[ embassy_executor:: task]
371+ async fn bc_test_task ( mut tx : EspNowSender < ' static > , manager : EspNowManager < ' static > ) {
372+ let mut counter = 0u128 ;
373+ loop {
374+ manager
375+ . add_peer ( esp_wifi:: esp_now:: PeerInfo {
376+ peer_address : * ESP_NOW_DST ,
377+ lmk : None ,
378+ channel : None ,
379+ encrypt : false ,
380+ } )
381+ . unwrap ( ) ;
382+
383+ let r = tx. send_async ( ESP_NOW_DST , & counter. to_be_bytes ( ) ) . await ;
384+ manager. remove_peer ( ESP_NOW_DST ) . unwrap ( ) ;
385+
386+ counter += 1 ;
387+ Timer :: after_millis ( 1000 ) . await ;
388+ }
389+ }
0 commit comments